1cf69771bSopenharmony_ci/*
2cf69771bSopenharmony_ci * Copyright (C) 2022-2023 Huawei Device Co., Ltd.
3cf69771bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4cf69771bSopenharmony_ci * you may not use this file except in compliance with the License.
5cf69771bSopenharmony_ci * You may obtain a copy of the License at
6cf69771bSopenharmony_ci *
7cf69771bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8cf69771bSopenharmony_ci *
9cf69771bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10cf69771bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11cf69771bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12cf69771bSopenharmony_ci * See the License for the specific language governing permissions and
13cf69771bSopenharmony_ci * limitations under the License.
14cf69771bSopenharmony_ci */
15cf69771bSopenharmony_ci
16cf69771bSopenharmony_ci#include "timer_manager.h"
17cf69771bSopenharmony_ci
18cf69771bSopenharmony_ci#include <algorithm>
19cf69771bSopenharmony_ci#include <ctime>
20cf69771bSopenharmony_ci#include <iostream>
21cf69771bSopenharmony_ci#include <sys/time.h>
22cf69771bSopenharmony_ci#include <utility>
23cf69771bSopenharmony_ci#include <vector>
24cf69771bSopenharmony_ci
25cf69771bSopenharmony_ci#include "system_ability_definition.h"
26cf69771bSopenharmony_ci#include "rdb_errno.h"
27cf69771bSopenharmony_ci#include "rdb_helper.h"
28cf69771bSopenharmony_ci#include "rdb_open_callback.h"
29cf69771bSopenharmony_ci#include "rdb_predicates.h"
30cf69771bSopenharmony_ci#include "rdb_store.h"
31cf69771bSopenharmony_ci#ifdef DEVICE_STANDBY_ENABLE
32cf69771bSopenharmony_ci#include "allow_type.h"
33cf69771bSopenharmony_ci#include "standby_service_client.h"
34cf69771bSopenharmony_ci#endif
35cf69771bSopenharmony_ci#include "ipc_skeleton.h"
36cf69771bSopenharmony_ci#include "time_file_utils.h"
37cf69771bSopenharmony_ci#include "time_permission.h"
38cf69771bSopenharmony_ci#include "timer_proxy.h"
39cf69771bSopenharmony_ci#include "time_sysevent.h"
40cf69771bSopenharmony_ci#include "timer_database.h"
41cf69771bSopenharmony_ci#include "os_account.h"
42cf69771bSopenharmony_ci#include "os_account_manager.h"
43cf69771bSopenharmony_ci#ifdef POWER_MANAGER_ENABLE
44cf69771bSopenharmony_ci#include "time_system_ability.h"
45cf69771bSopenharmony_ci#endif
46cf69771bSopenharmony_ci
47cf69771bSopenharmony_cinamespace OHOS {
48cf69771bSopenharmony_cinamespace MiscServices {
49cf69771bSopenharmony_ciusing namespace std::chrono;
50cf69771bSopenharmony_ciusing namespace OHOS::AppExecFwk;
51cf69771bSopenharmony_cinamespace {
52cf69771bSopenharmony_ciconstexpr uint32_t TIME_CHANGED_BITS = 16;
53cf69771bSopenharmony_ciconstexpr uint32_t TIME_CHANGED_MASK = 1 << TIME_CHANGED_BITS;
54cf69771bSopenharmony_ciconstexpr int64_t MAX_MILLISECOND = std::numeric_limits<int64_t>::max() / 1000000;
55cf69771bSopenharmony_ciconst int ONE_THOUSAND = 1000;
56cf69771bSopenharmony_ciconst float_t BATCH_WINDOW_COE = 0.75;
57cf69771bSopenharmony_ciconst auto ZERO_FUTURITY = seconds(0);
58cf69771bSopenharmony_ciconst auto MIN_INTERVAL_ONE_SECONDS = seconds(1);
59cf69771bSopenharmony_ciconst auto MAX_INTERVAL = hours(24 * 365);
60cf69771bSopenharmony_ciconst auto INTERVAL_HOUR = hours(1);
61cf69771bSopenharmony_ciconst auto INTERVAL_HALF_DAY = hours(12);
62cf69771bSopenharmony_ciconst auto MIN_FUZZABLE_INTERVAL = milliseconds(10000);
63cf69771bSopenharmony_ciconst int NANO_TO_SECOND =  1000000000;
64cf69771bSopenharmony_ciconst int WANTAGENT_CODE_ELEVEN = 11;
65cf69771bSopenharmony_ciconst int WANT_RETRY_TIMES = 6;
66cf69771bSopenharmony_ciconst int WANT_RETRY_INTERVAL = 1;
67cf69771bSopenharmony_ciconst int SYSTEM_USER_ID  = 0;
68cf69771bSopenharmony_ci// an error code of ipc which means peer end is dead
69cf69771bSopenharmony_ciconstexpr int PEER_END_DEAD = 29189;
70cf69771bSopenharmony_cistatic const std::vector<std::string> ALL_DATA = { "timerId", "type", "flag", "windowLength", "interval", \
71cf69771bSopenharmony_ci                                                   "uid", "bundleName", "wantAgent", "state", "triggerTime" };
72cf69771bSopenharmony_ci
73cf69771bSopenharmony_ci#ifdef POWER_MANAGER_ENABLE
74cf69771bSopenharmony_ciconstexpr int64_t USE_LOCK_ONE_SEC_IN_NANO = 1 * NANO_TO_SECOND;
75cf69771bSopenharmony_ciconstexpr int64_t USE_LOCK_TIME_IN_NANO = 2 * NANO_TO_SECOND;
76cf69771bSopenharmony_ciconstexpr int32_t NANO_TO_MILLI = 1000000;
77cf69771bSopenharmony_ciconstexpr int64_t ONE_HUNDRED_MILLI = 100000000; // 100ms
78cf69771bSopenharmony_ciconst int POWER_RETRY_TIMES = 10;
79cf69771bSopenharmony_ciconst int POWER_RETRY_INTERVAL = 10000;
80cf69771bSopenharmony_ci#endif
81cf69771bSopenharmony_ci
82cf69771bSopenharmony_ci#ifdef DEVICE_STANDBY_ENABLE
83cf69771bSopenharmony_ciconst int REASON_NATIVE_API = 0;
84cf69771bSopenharmony_ciconst int REASON_APP_API = 1;
85cf69771bSopenharmony_ci#endif
86cf69771bSopenharmony_ci}
87cf69771bSopenharmony_ci
88cf69771bSopenharmony_cistd::mutex TimerManager::instanceLock_;
89cf69771bSopenharmony_ciTimerManager* TimerManager::instance_ = nullptr;
90cf69771bSopenharmony_ci
91cf69771bSopenharmony_ciextern bool AddBatchLocked(std::vector<std::shared_ptr<Batch>> &list, const std::shared_ptr<Batch> &batch);
92cf69771bSopenharmony_ciextern steady_clock::time_point MaxTriggerTime(steady_clock::time_point now,
93cf69771bSopenharmony_ci                                               steady_clock::time_point triggerAtTime,
94cf69771bSopenharmony_ci                                               milliseconds interval);
95cf69771bSopenharmony_ci
96cf69771bSopenharmony_ciTimerManager::TimerManager(std::shared_ptr<TimerHandler> impl)
97cf69771bSopenharmony_ci    : random_ {static_cast<uint64_t>(time(nullptr))},
98cf69771bSopenharmony_ci      runFlag_ {true},
99cf69771bSopenharmony_ci      handler_ {std::move(impl)},
100cf69771bSopenharmony_ci      lastTimeChangeClockTime_ {system_clock::time_point::min()},
101cf69771bSopenharmony_ci      lastTimeChangeRealtime_ {steady_clock::time_point::min()}
102cf69771bSopenharmony_ci{
103cf69771bSopenharmony_ci    alarmThread_.reset(new std::thread([this] { this->TimerLooper(); }));
104cf69771bSopenharmony_ci}
105cf69771bSopenharmony_ci
106cf69771bSopenharmony_ciTimerManager* TimerManager::GetInstance()
107cf69771bSopenharmony_ci{
108cf69771bSopenharmony_ci    if (instance_ == nullptr) {
109cf69771bSopenharmony_ci        std::lock_guard<std::mutex> autoLock(instanceLock_);
110cf69771bSopenharmony_ci        if (instance_ == nullptr) {
111cf69771bSopenharmony_ci            auto impl = TimerHandler::Create();
112cf69771bSopenharmony_ci            if (impl == nullptr) {
113cf69771bSopenharmony_ci                TIME_HILOGE(TIME_MODULE_SERVICE, "Create Timer handle failed.");
114cf69771bSopenharmony_ci                return nullptr;
115cf69771bSopenharmony_ci            }
116cf69771bSopenharmony_ci            instance_ = new TimerManager(impl);
117cf69771bSopenharmony_ci            std::vector<std::string> bundleList = TimeFileUtils::GetBundleList();
118cf69771bSopenharmony_ci            if (!bundleList.empty()) {
119cf69771bSopenharmony_ci                NEED_RECOVER_ON_REBOOT = bundleList;
120cf69771bSopenharmony_ci            }
121cf69771bSopenharmony_ci        }
122cf69771bSopenharmony_ci    }
123cf69771bSopenharmony_ci    if (instance_ == nullptr) {
124cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "Create Timer manager failed.");
125cf69771bSopenharmony_ci    }
126cf69771bSopenharmony_ci    return instance_;
127cf69771bSopenharmony_ci}
128cf69771bSopenharmony_ci
129cf69771bSopenharmony_ciOHOS::NativeRdb::ValuesBucket GetInsertValues(std::shared_ptr<TimerEntry> timerInfo, TimerPara &paras)
130cf69771bSopenharmony_ci{
131cf69771bSopenharmony_ci    OHOS::NativeRdb::ValuesBucket insertValues;
132cf69771bSopenharmony_ci    insertValues.PutLong("timerId", timerInfo->id);
133cf69771bSopenharmony_ci    insertValues.PutInt("type", paras.timerType);
134cf69771bSopenharmony_ci    insertValues.PutInt("flag", paras.flag);
135cf69771bSopenharmony_ci    insertValues.PutLong("windowLength", paras.windowLength);
136cf69771bSopenharmony_ci    insertValues.PutLong("interval", paras.interval);
137cf69771bSopenharmony_ci    insertValues.PutInt("uid", timerInfo->uid);
138cf69771bSopenharmony_ci    insertValues.PutString("bundleName", timerInfo->bundleName);
139cf69771bSopenharmony_ci    insertValues.PutString("wantAgent",
140cf69771bSopenharmony_ci        OHOS::AbilityRuntime::WantAgent::WantAgentHelper::ToString(timerInfo->wantAgent));
141cf69771bSopenharmony_ci    insertValues.PutInt("state", 0);
142cf69771bSopenharmony_ci    insertValues.PutLong("triggerTime", 0);
143cf69771bSopenharmony_ci    insertValues.PutInt("pid", timerInfo->pid);
144cf69771bSopenharmony_ci    return insertValues;
145cf69771bSopenharmony_ci}
146cf69771bSopenharmony_ci
147cf69771bSopenharmony_ciint32_t TimerManager::CreateTimer(TimerPara &paras,
148cf69771bSopenharmony_ci                                  std::function<int32_t (const uint64_t)> callback,
149cf69771bSopenharmony_ci                                  std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> wantAgent,
150cf69771bSopenharmony_ci                                  int uid,
151cf69771bSopenharmony_ci                                  int pid,
152cf69771bSopenharmony_ci                                  uint64_t &timerId,
153cf69771bSopenharmony_ci                                  DatabaseType type)
154cf69771bSopenharmony_ci{
155cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE,
156cf69771bSopenharmony_ci                "Create timer: %{public}d windowLength:%{public}" PRId64 "interval:%{public}" PRId64 "flag:%{public}d"
157cf69771bSopenharmony_ci                "uid:%{public}d pid:%{public}d timerId:%{public}" PRId64 "", paras.timerType, paras.windowLength,
158cf69771bSopenharmony_ci                paras.interval, paras.flag, IPCSkeleton::GetCallingUid(), IPCSkeleton::GetCallingPid(), timerId);
159cf69771bSopenharmony_ci    std::string bundleName = TimeFileUtils::GetBundleNameByTokenID(IPCSkeleton::GetCallingTokenID());
160cf69771bSopenharmony_ci    if (bundleName.empty()) {
161cf69771bSopenharmony_ci        bundleName = TimeFileUtils::GetNameByPid(IPCSkeleton::GetCallingPid());
162cf69771bSopenharmony_ci    }
163cf69771bSopenharmony_ci    std::shared_ptr<TimerEntry> timerInfo;
164cf69771bSopenharmony_ci    {
165cf69771bSopenharmony_ci        std::lock_guard<std::mutex> lock(entryMapMutex_);
166cf69771bSopenharmony_ci        while (timerId == 0) {
167cf69771bSopenharmony_ci            // random_() needs to be protected in a lock.
168cf69771bSopenharmony_ci            timerId = random_();
169cf69771bSopenharmony_ci        }
170cf69771bSopenharmony_ci        timerInfo = std::make_shared<TimerEntry>(TimerEntry {
171cf69771bSopenharmony_ci            timerId,
172cf69771bSopenharmony_ci            paras.timerType,
173cf69771bSopenharmony_ci            paras.windowLength,
174cf69771bSopenharmony_ci            paras.interval,
175cf69771bSopenharmony_ci            paras.flag,
176cf69771bSopenharmony_ci            std::move(callback),
177cf69771bSopenharmony_ci            wantAgent,
178cf69771bSopenharmony_ci            uid,
179cf69771bSopenharmony_ci            pid,
180cf69771bSopenharmony_ci            bundleName
181cf69771bSopenharmony_ci        });
182cf69771bSopenharmony_ci        timerEntryMap_.insert(std::make_pair(timerId, timerInfo));
183cf69771bSopenharmony_ci    }
184cf69771bSopenharmony_ci
185cf69771bSopenharmony_ci    if (type == NOT_STORE) {
186cf69771bSopenharmony_ci        return E_TIME_OK;
187cf69771bSopenharmony_ci    } else if (CheckNeedRecoverOnReboot(bundleName, paras.timerType)) {
188cf69771bSopenharmony_ci        TimeDatabase::GetInstance().Insert(std::string(HOLD_ON_REBOOT),
189cf69771bSopenharmony_ci                                           GetInsertValues(timerInfo, paras));
190cf69771bSopenharmony_ci    } else {
191cf69771bSopenharmony_ci        TimeDatabase::GetInstance().Insert(std::string(DROP_ON_REBOOT),
192cf69771bSopenharmony_ci                                           GetInsertValues(timerInfo, paras));
193cf69771bSopenharmony_ci    }
194cf69771bSopenharmony_ci    return E_TIME_OK;
195cf69771bSopenharmony_ci}
196cf69771bSopenharmony_ci
197cf69771bSopenharmony_civoid TimerManager::ReCreateTimer(uint64_t timerId, std::shared_ptr<TimerEntry> timerInfo)
198cf69771bSopenharmony_ci{
199cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(entryMapMutex_);
200cf69771bSopenharmony_ci    timerEntryMap_.insert(std::make_pair(timerId, timerInfo));
201cf69771bSopenharmony_ci}
202cf69771bSopenharmony_ci
203cf69771bSopenharmony_ciint32_t TimerManager::StartTimer(uint64_t timerId, uint64_t triggerTime)
204cf69771bSopenharmony_ci{
205cf69771bSopenharmony_ci    std::shared_ptr<TimerEntry> timerInfo;
206cf69771bSopenharmony_ci    {
207cf69771bSopenharmony_ci        std::lock_guard<std::mutex> lock(entryMapMutex_);
208cf69771bSopenharmony_ci        auto it = timerEntryMap_.find(timerId);
209cf69771bSopenharmony_ci        if (it == timerEntryMap_.end()) {
210cf69771bSopenharmony_ci            TIME_HILOGE(TIME_MODULE_SERVICE, "Timer id not found: %{public}" PRId64 "", timerId);
211cf69771bSopenharmony_ci            return E_TIME_NOT_FOUND;
212cf69771bSopenharmony_ci        }
213cf69771bSopenharmony_ci        timerInfo = it->second;
214cf69771bSopenharmony_ci    }
215cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE,
216cf69771bSopenharmony_ci        "id: %{public}" PRIu64 " typ:%{public}d len: %{public}" PRId64 " int: %{public}" PRId64 " "
217cf69771bSopenharmony_ci        "flg :%{public}d trig: %{public}s uid:%{public}d pid:%{public}d",
218cf69771bSopenharmony_ci        timerId, timerInfo->type, timerInfo->windowLength, timerInfo->interval, timerInfo->flag,
219cf69771bSopenharmony_ci        std::to_string(triggerTime).c_str(), IPCSkeleton::GetCallingUid(), IPCSkeleton::GetCallingPid());
220cf69771bSopenharmony_ci    {
221cf69771bSopenharmony_ci        // To prevent the same ID from being started repeatedly,
222cf69771bSopenharmony_ci        // the later start overwrites the earlier start.
223cf69771bSopenharmony_ci        std::lock_guard<std::mutex> lock(mutex_);
224cf69771bSopenharmony_ci        RemoveLocked(timerId, false);
225cf69771bSopenharmony_ci    }
226cf69771bSopenharmony_ci    SetHandler(timerInfo->id, timerInfo->type, triggerTime, timerInfo->windowLength, timerInfo->interval,
227cf69771bSopenharmony_ci               timerInfo->flag, timerInfo->callback, timerInfo->wantAgent, timerInfo->uid, timerInfo->pid,
228cf69771bSopenharmony_ci               timerInfo->bundleName);
229cf69771bSopenharmony_ci    auto tableName = (CheckNeedRecoverOnReboot(timerInfo->bundleName, timerInfo->type)
230cf69771bSopenharmony_ci                      ? HOLD_ON_REBOOT
231cf69771bSopenharmony_ci                      : DROP_ON_REBOOT);
232cf69771bSopenharmony_ci    OHOS::NativeRdb::ValuesBucket values;
233cf69771bSopenharmony_ci    values.PutInt("state", 1);
234cf69771bSopenharmony_ci    values.PutLong("triggerTime", static_cast<int64_t>(triggerTime));
235cf69771bSopenharmony_ci    OHOS::NativeRdb::RdbPredicates rdbPredicates(tableName);
236cf69771bSopenharmony_ci    rdbPredicates.EqualTo("state", 0)->And()->EqualTo("timerId", static_cast<int64_t>(timerId));
237cf69771bSopenharmony_ci    TimeDatabase::GetInstance().Update(values, rdbPredicates);
238cf69771bSopenharmony_ci    return E_TIME_OK;
239cf69771bSopenharmony_ci}
240cf69771bSopenharmony_ci
241cf69771bSopenharmony_ciint32_t TimerManager::StopTimer(uint64_t timerId)
242cf69771bSopenharmony_ci{
243cf69771bSopenharmony_ci    return StopTimerInner(timerId, false);
244cf69771bSopenharmony_ci}
245cf69771bSopenharmony_ci
246cf69771bSopenharmony_ciint32_t TimerManager::DestroyTimer(uint64_t timerId)
247cf69771bSopenharmony_ci{
248cf69771bSopenharmony_ci    return StopTimerInner(timerId, true);
249cf69771bSopenharmony_ci}
250cf69771bSopenharmony_ci
251cf69771bSopenharmony_ciint32_t TimerManager::StopTimerInner(uint64_t timerNumber, bool needDestroy)
252cf69771bSopenharmony_ci{
253cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE, "id: %{public}" PRId64 ", needDestroy: %{public}d", timerNumber, needDestroy);
254cf69771bSopenharmony_ci    bool needRecoverOnReboot;
255cf69771bSopenharmony_ci    {
256cf69771bSopenharmony_ci        std::lock_guard<std::mutex> lock(entryMapMutex_);
257cf69771bSopenharmony_ci        auto it = timerEntryMap_.find(timerNumber);
258cf69771bSopenharmony_ci        if (it == timerEntryMap_.end()) {
259cf69771bSopenharmony_ci            TIME_HILOGW(TIME_MODULE_SERVICE, "timer not exist");
260cf69771bSopenharmony_ci            return E_TIME_DEAL_FAILED;
261cf69771bSopenharmony_ci        }
262cf69771bSopenharmony_ci        RemoveHandler(timerNumber);
263cf69771bSopenharmony_ci        TimerProxy::GetInstance().RemoveProxy(timerNumber, it->second->uid);
264cf69771bSopenharmony_ci        TimerProxy::GetInstance().RemovePidProxy(timerNumber, it->second->pid);
265cf69771bSopenharmony_ci        TimerProxy::GetInstance().EraseTimerFromProxyUidMap(timerNumber, it->second->uid);
266cf69771bSopenharmony_ci        TimerProxy::GetInstance().EraseTimerFromProxyPidMap(timerNumber, it->second->pid);
267cf69771bSopenharmony_ci        needRecoverOnReboot = CheckNeedRecoverOnReboot(it->second->bundleName, it->second->type);
268cf69771bSopenharmony_ci        if (needDestroy) { timerEntryMap_.erase(it); }
269cf69771bSopenharmony_ci    }
270cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE, "db bgn");
271cf69771bSopenharmony_ci    if (needRecoverOnReboot) {
272cf69771bSopenharmony_ci        OHOS::NativeRdb::ValuesBucket values;
273cf69771bSopenharmony_ci        values.PutInt("state", 0);
274cf69771bSopenharmony_ci        OHOS::NativeRdb::RdbPredicates rdbPredicates(HOLD_ON_REBOOT);
275cf69771bSopenharmony_ci        rdbPredicates.EqualTo("state", 1)->And()->EqualTo("timerId", static_cast<int64_t>(timerNumber));
276cf69771bSopenharmony_ci        TimeDatabase::GetInstance().Update(values, rdbPredicates);
277cf69771bSopenharmony_ci        if (needDestroy) {
278cf69771bSopenharmony_ci            OHOS::NativeRdb::RdbPredicates rdbPredicatesDelete(HOLD_ON_REBOOT);
279cf69771bSopenharmony_ci            rdbPredicatesDelete.EqualTo("timerId", static_cast<int64_t>(timerNumber));
280cf69771bSopenharmony_ci            TIME_HILOGI(TIME_MODULE_SERVICE, "db del");
281cf69771bSopenharmony_ci            TimeDatabase::GetInstance().Delete(rdbPredicatesDelete);
282cf69771bSopenharmony_ci        }
283cf69771bSopenharmony_ci    } else {
284cf69771bSopenharmony_ci        OHOS::NativeRdb::ValuesBucket values;
285cf69771bSopenharmony_ci        values.PutInt("state", 0);
286cf69771bSopenharmony_ci        OHOS::NativeRdb::RdbPredicates rdbPredicates(DROP_ON_REBOOT);
287cf69771bSopenharmony_ci        rdbPredicates.EqualTo("state", 1)->And()->EqualTo("timerId", static_cast<int64_t>(timerNumber));
288cf69771bSopenharmony_ci        TimeDatabase::GetInstance().Update(values, rdbPredicates);
289cf69771bSopenharmony_ci        if (needDestroy) {
290cf69771bSopenharmony_ci            OHOS::NativeRdb::RdbPredicates rdbPredicatesDelete(DROP_ON_REBOOT);
291cf69771bSopenharmony_ci            rdbPredicatesDelete.EqualTo("timerId", static_cast<int64_t>(timerNumber));
292cf69771bSopenharmony_ci            TIME_HILOGI(TIME_MODULE_SERVICE, "db del");
293cf69771bSopenharmony_ci            TimeDatabase::GetInstance().Delete(rdbPredicatesDelete);
294cf69771bSopenharmony_ci        }
295cf69771bSopenharmony_ci    }
296cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE, "db end");
297cf69771bSopenharmony_ci    return E_TIME_OK;
298cf69771bSopenharmony_ci}
299cf69771bSopenharmony_ci
300cf69771bSopenharmony_civoid TimerManager::SetHandler(uint64_t id,
301cf69771bSopenharmony_ci                              int type,
302cf69771bSopenharmony_ci                              uint64_t triggerAtTime,
303cf69771bSopenharmony_ci                              int64_t windowLength,
304cf69771bSopenharmony_ci                              uint64_t interval,
305cf69771bSopenharmony_ci                              int flag,
306cf69771bSopenharmony_ci                              std::function<int32_t (const uint64_t)> callback,
307cf69771bSopenharmony_ci                              std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> wantAgent,
308cf69771bSopenharmony_ci                              int uid,
309cf69771bSopenharmony_ci                              int pid,
310cf69771bSopenharmony_ci                              const std::string &bundleName)
311cf69771bSopenharmony_ci{
312cf69771bSopenharmony_ci    auto windowLengthDuration = milliseconds(windowLength);
313cf69771bSopenharmony_ci    if (windowLengthDuration > INTERVAL_HALF_DAY) {
314cf69771bSopenharmony_ci        windowLengthDuration = INTERVAL_HOUR;
315cf69771bSopenharmony_ci    }
316cf69771bSopenharmony_ci    auto intervalDuration = milliseconds(interval > MAX_MILLISECOND ? MAX_MILLISECOND : interval);
317cf69771bSopenharmony_ci    if (intervalDuration > milliseconds::zero() && intervalDuration < MIN_INTERVAL_ONE_SECONDS) {
318cf69771bSopenharmony_ci        intervalDuration = MIN_INTERVAL_ONE_SECONDS;
319cf69771bSopenharmony_ci    } else if (intervalDuration > MAX_INTERVAL) {
320cf69771bSopenharmony_ci        intervalDuration = MAX_INTERVAL;
321cf69771bSopenharmony_ci    }
322cf69771bSopenharmony_ci
323cf69771bSopenharmony_ci    auto nowElapsed = GetBootTimeNs();
324cf69771bSopenharmony_ci    auto when = milliseconds(triggerAtTime > MAX_MILLISECOND ? MAX_MILLISECOND : triggerAtTime);
325cf69771bSopenharmony_ci    auto nominalTrigger = ConvertToElapsed(when, type);
326cf69771bSopenharmony_ci    auto minTrigger = nowElapsed + ZERO_FUTURITY;
327cf69771bSopenharmony_ci    auto triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
328cf69771bSopenharmony_ci
329cf69771bSopenharmony_ci    steady_clock::time_point maxElapsed;
330cf69771bSopenharmony_ci    if (windowLengthDuration == milliseconds::zero()) {
331cf69771bSopenharmony_ci        maxElapsed = triggerElapsed;
332cf69771bSopenharmony_ci    } else if (windowLengthDuration < milliseconds::zero()) {
333cf69771bSopenharmony_ci        maxElapsed = MaxTriggerTime(nominalTrigger, triggerElapsed, intervalDuration);
334cf69771bSopenharmony_ci        windowLengthDuration = duration_cast<milliseconds>(maxElapsed - triggerElapsed);
335cf69771bSopenharmony_ci    } else {
336cf69771bSopenharmony_ci        maxElapsed = triggerElapsed + windowLengthDuration;
337cf69771bSopenharmony_ci    }
338cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lockGuard(mutex_);
339cf69771bSopenharmony_ci    SetHandlerLocked(id,
340cf69771bSopenharmony_ci                     type,
341cf69771bSopenharmony_ci                     when,
342cf69771bSopenharmony_ci                     triggerElapsed,
343cf69771bSopenharmony_ci                     windowLengthDuration,
344cf69771bSopenharmony_ci                     maxElapsed,
345cf69771bSopenharmony_ci                     intervalDuration,
346cf69771bSopenharmony_ci                     std::move(callback),
347cf69771bSopenharmony_ci                     wantAgent,
348cf69771bSopenharmony_ci                     static_cast<uint32_t>(flag),
349cf69771bSopenharmony_ci                     uid,
350cf69771bSopenharmony_ci                     pid,
351cf69771bSopenharmony_ci                     bundleName);
352cf69771bSopenharmony_ci}
353cf69771bSopenharmony_ci
354cf69771bSopenharmony_civoid TimerManager::SetHandlerLocked(uint64_t id, int type,
355cf69771bSopenharmony_ci                                    std::chrono::milliseconds when,
356cf69771bSopenharmony_ci                                    std::chrono::steady_clock::time_point whenElapsed,
357cf69771bSopenharmony_ci                                    std::chrono::milliseconds windowLength,
358cf69771bSopenharmony_ci                                    std::chrono::steady_clock::time_point maxWhen,
359cf69771bSopenharmony_ci                                    std::chrono::milliseconds interval,
360cf69771bSopenharmony_ci                                    std::function<int32_t (const uint64_t)> callback,
361cf69771bSopenharmony_ci                                    const std::shared_ptr<OHOS::AbilityRuntime::WantAgent::WantAgent> &wantAgent,
362cf69771bSopenharmony_ci                                    uint32_t flags,
363cf69771bSopenharmony_ci                                    uint64_t callingUid,
364cf69771bSopenharmony_ci                                    uint64_t callingPid,
365cf69771bSopenharmony_ci                                    const std::string &bundleName)
366cf69771bSopenharmony_ci{
367cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "start id: %{public}" PRId64 "", id);
368cf69771bSopenharmony_ci    auto alarm = std::make_shared<TimerInfo>(id, type, when, whenElapsed, windowLength, maxWhen,
369cf69771bSopenharmony_ci                                             interval, std::move(callback), wantAgent, flags, callingUid,
370cf69771bSopenharmony_ci                                             callingPid, bundleName);
371cf69771bSopenharmony_ci    if (TimerProxy::GetInstance().IsUidProxy(alarm->uid)) {
372cf69771bSopenharmony_ci        TIME_HILOGI(TIME_MODULE_SERVICE, "Timer already proxy, uid=%{public}" PRIu64 " id=%{public}" PRId64 "",
373cf69771bSopenharmony_ci            callingUid, alarm->id);
374cf69771bSopenharmony_ci        TimerProxy::GetInstance().RecordProxyUidTimerMap(alarm);
375cf69771bSopenharmony_ci        alarm->UpdateWhenElapsedFromNow(whenElapsed, milliseconds(TimerProxy::GetInstance().GetProxyDelayTime()));
376cf69771bSopenharmony_ci    }
377cf69771bSopenharmony_ci    if (TimerProxy::GetInstance().IsPidProxy(alarm->pid)) {
378cf69771bSopenharmony_ci        TIME_HILOGI(TIME_MODULE_SERVICE, "Timer already proxy, pid=%{public}" PRIu64 " id=%{public}" PRId64 "",
379cf69771bSopenharmony_ci            callingPid, alarm->id);
380cf69771bSopenharmony_ci        TimerProxy::GetInstance().RecordProxyPidTimerMap(alarm);
381cf69771bSopenharmony_ci        alarm->UpdateWhenElapsedFromNow(whenElapsed, milliseconds(TimerProxy::GetInstance().GetProxyDelayTime()));
382cf69771bSopenharmony_ci    }
383cf69771bSopenharmony_ci
384cf69771bSopenharmony_ci    SetHandlerLocked(alarm, false, false);
385cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "end");
386cf69771bSopenharmony_ci}
387cf69771bSopenharmony_ci
388cf69771bSopenharmony_civoid TimerManager::RemoveHandler(uint64_t id)
389cf69771bSopenharmony_ci{
390cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
391cf69771bSopenharmony_ci    RemoveLocked(id, true);
392cf69771bSopenharmony_ci    TimerProxy::GetInstance().RemoveUidTimerMap(id);
393cf69771bSopenharmony_ci    TimerProxy::GetInstance().RemovePidTimerMap(id);
394cf69771bSopenharmony_ci}
395cf69771bSopenharmony_ci
396cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
397cf69771bSopenharmony_civoid TimerManager::RemoveLocked(uint64_t id, bool needReschedule)
398cf69771bSopenharmony_ci{
399cf69771bSopenharmony_ci    auto whichAlarms = [id](const TimerInfo &timer) {
400cf69771bSopenharmony_ci        return timer.id == id;
401cf69771bSopenharmony_ci    };
402cf69771bSopenharmony_ci
403cf69771bSopenharmony_ci    bool didRemove = false;
404cf69771bSopenharmony_ci    for (auto it = alarmBatches_.begin(); it != alarmBatches_.end();) {
405cf69771bSopenharmony_ci        auto batch = *it;
406cf69771bSopenharmony_ci        didRemove = batch->Remove(whichAlarms);
407cf69771bSopenharmony_ci        if (didRemove) {
408cf69771bSopenharmony_ci            TIME_HILOGI(TIME_MODULE_SERVICE, "remove id: %{public}" PRIu64 "", id);
409cf69771bSopenharmony_ci            it = alarmBatches_.erase(it);
410cf69771bSopenharmony_ci            if (batch->Size() != 0) {
411cf69771bSopenharmony_ci                TIME_HILOGI(TIME_MODULE_SERVICE, "reorder batch");
412cf69771bSopenharmony_ci                AddBatchLocked(alarmBatches_, batch);
413cf69771bSopenharmony_ci            }
414cf69771bSopenharmony_ci            break;
415cf69771bSopenharmony_ci        }
416cf69771bSopenharmony_ci        ++it;
417cf69771bSopenharmony_ci    }
418cf69771bSopenharmony_ci    pendingDelayTimers_.erase(remove_if(pendingDelayTimers_.begin(), pendingDelayTimers_.end(),
419cf69771bSopenharmony_ci        [id](const std::shared_ptr<TimerInfo> &timer) {
420cf69771bSopenharmony_ci            return timer->id == id;
421cf69771bSopenharmony_ci        }), pendingDelayTimers_.end());
422cf69771bSopenharmony_ci    delayedTimers_.erase(id);
423cf69771bSopenharmony_ci    if (mPendingIdleUntil_ != nullptr && id == mPendingIdleUntil_->id) {
424cf69771bSopenharmony_ci        TIME_HILOGI(TIME_MODULE_SERVICE, "Idle alarm removed.");
425cf69771bSopenharmony_ci        mPendingIdleUntil_ = nullptr;
426cf69771bSopenharmony_ci        bool isAdjust = AdjustTimersBasedOnDeviceIdle();
427cf69771bSopenharmony_ci        delayedTimers_.clear();
428cf69771bSopenharmony_ci        for (const auto &pendingTimer : pendingDelayTimers_) {
429cf69771bSopenharmony_ci            TIME_HILOGI(TIME_MODULE_SERVICE, "Set timer from delay list, id=%{public}" PRId64 "", pendingTimer->id);
430cf69771bSopenharmony_ci            if (pendingTimer->whenElapsed <= GetBootTimeNs()) {
431cf69771bSopenharmony_ci                // 2 means the time of performing task.
432cf69771bSopenharmony_ci                pendingTimer->UpdateWhenElapsedFromNow(GetBootTimeNs(), milliseconds(2));
433cf69771bSopenharmony_ci            } else {
434cf69771bSopenharmony_ci                pendingTimer->UpdateWhenElapsedFromNow(GetBootTimeNs(), pendingTimer->offset);
435cf69771bSopenharmony_ci            }
436cf69771bSopenharmony_ci            SetHandlerLocked(pendingTimer, false, false);
437cf69771bSopenharmony_ci        }
438cf69771bSopenharmony_ci        pendingDelayTimers_.clear();
439cf69771bSopenharmony_ci        if (isAdjust) {
440cf69771bSopenharmony_ci            ReBatchAllTimers();
441cf69771bSopenharmony_ci            return;
442cf69771bSopenharmony_ci        }
443cf69771bSopenharmony_ci    }
444cf69771bSopenharmony_ci
445cf69771bSopenharmony_ci    if (needReschedule && didRemove) {
446cf69771bSopenharmony_ci        RescheduleKernelTimerLocked();
447cf69771bSopenharmony_ci    }
448cf69771bSopenharmony_ci}
449cf69771bSopenharmony_ci
450cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
451cf69771bSopenharmony_civoid TimerManager::SetHandlerLocked(std::shared_ptr<TimerInfo> alarm, bool rebatching, bool isRebatched)
452cf69771bSopenharmony_ci{
453cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "start rebatching= %{public}d", rebatching);
454cf69771bSopenharmony_ci    TimerProxy::GetInstance().RecordUidTimerMap(alarm, isRebatched);
455cf69771bSopenharmony_ci    TimerProxy::GetInstance().RecordPidTimerMap(alarm, isRebatched);
456cf69771bSopenharmony_ci
457cf69771bSopenharmony_ci    if (!isRebatched && mPendingIdleUntil_ != nullptr && !CheckAllowWhileIdle(alarm)) {
458cf69771bSopenharmony_ci        TIME_HILOGI(TIME_MODULE_SERVICE, "Pending not-allowed alarm in idle state, id=%{public}" PRId64 "",
459cf69771bSopenharmony_ci            alarm->id);
460cf69771bSopenharmony_ci        alarm->offset = duration_cast<milliseconds>(alarm->whenElapsed - GetBootTimeNs());
461cf69771bSopenharmony_ci        pendingDelayTimers_.push_back(alarm);
462cf69771bSopenharmony_ci        return;
463cf69771bSopenharmony_ci    }
464cf69771bSopenharmony_ci    if (!rebatching) {
465cf69771bSopenharmony_ci        AdjustSingleTimer(alarm);
466cf69771bSopenharmony_ci    }
467cf69771bSopenharmony_ci    bool isAdjust = false;
468cf69771bSopenharmony_ci    if (!isRebatched && alarm->flags & static_cast<uint32_t>(IDLE_UNTIL)) {
469cf69771bSopenharmony_ci        TIME_HILOGI(TIME_MODULE_SERVICE, "Set idle timer, id=%{public}" PRId64 "", alarm->id);
470cf69771bSopenharmony_ci        mPendingIdleUntil_ = alarm;
471cf69771bSopenharmony_ci        isAdjust = AdjustTimersBasedOnDeviceIdle();
472cf69771bSopenharmony_ci    }
473cf69771bSopenharmony_ci    InsertAndBatchTimerLocked(std::move(alarm));
474cf69771bSopenharmony_ci    if (isAdjust) {
475cf69771bSopenharmony_ci        ReBatchAllTimers();
476cf69771bSopenharmony_ci        rebatching = true;
477cf69771bSopenharmony_ci    }
478cf69771bSopenharmony_ci    if (!rebatching) {
479cf69771bSopenharmony_ci        RescheduleKernelTimerLocked();
480cf69771bSopenharmony_ci    }
481cf69771bSopenharmony_ci}
482cf69771bSopenharmony_ci
483cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
484cf69771bSopenharmony_civoid TimerManager::ReBatchAllTimers()
485cf69771bSopenharmony_ci{
486cf69771bSopenharmony_ci    auto oldSet = alarmBatches_;
487cf69771bSopenharmony_ci    alarmBatches_.clear();
488cf69771bSopenharmony_ci    auto nowElapsed = GetBootTimeNs();
489cf69771bSopenharmony_ci    for (const auto &batch : oldSet) {
490cf69771bSopenharmony_ci        auto n = batch->Size();
491cf69771bSopenharmony_ci        for (unsigned int i = 0; i < n; i++) {
492cf69771bSopenharmony_ci            ReAddTimerLocked(batch->Get(i), nowElapsed);
493cf69771bSopenharmony_ci        }
494cf69771bSopenharmony_ci    }
495cf69771bSopenharmony_ci    RescheduleKernelTimerLocked();
496cf69771bSopenharmony_ci}
497cf69771bSopenharmony_ci
498cf69771bSopenharmony_civoid TimerManager::ReAddTimerLocked(std::shared_ptr<TimerInfo> timer,
499cf69771bSopenharmony_ci                                    std::chrono::steady_clock::time_point nowElapsed)
500cf69771bSopenharmony_ci{
501cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "ReAddTimerLocked start. uid= %{public}d, id=%{public}" PRId64 ""
502cf69771bSopenharmony_ci        ", timer originMaxWhenElapsed=%{public}lld, whenElapsed=%{public}lld, now=%{public}lld",
503cf69771bSopenharmony_ci        timer->uid, timer->id, timer->originWhenElapsed.time_since_epoch().count(),
504cf69771bSopenharmony_ci        timer->whenElapsed.time_since_epoch().count(), GetBootTimeNs().time_since_epoch().count());
505cf69771bSopenharmony_ci    auto whenElapsed = ConvertToElapsed(timer->when, timer->type);
506cf69771bSopenharmony_ci    steady_clock::time_point maxElapsed;
507cf69771bSopenharmony_ci    if (timer->windowLength == milliseconds::zero()) {
508cf69771bSopenharmony_ci        maxElapsed = whenElapsed;
509cf69771bSopenharmony_ci    } else {
510cf69771bSopenharmony_ci        maxElapsed = (timer->windowLength > milliseconds::zero()) ?
511cf69771bSopenharmony_ci                     (whenElapsed + timer->windowLength) :
512cf69771bSopenharmony_ci                     MaxTriggerTime(nowElapsed, whenElapsed, timer->repeatInterval);
513cf69771bSopenharmony_ci    }
514cf69771bSopenharmony_ci    timer->whenElapsed = whenElapsed;
515cf69771bSopenharmony_ci    timer->maxWhenElapsed = maxElapsed;
516cf69771bSopenharmony_ci    SetHandlerLocked(timer, true, true);
517cf69771bSopenharmony_ci}
518cf69771bSopenharmony_ci
519cf69771bSopenharmony_cistd::chrono::steady_clock::time_point TimerManager::ConvertToElapsed(std::chrono::milliseconds when, int type)
520cf69771bSopenharmony_ci{
521cf69771bSopenharmony_ci    auto bootTimePoint = GetBootTimeNs();
522cf69771bSopenharmony_ci    if (type == RTC || type == RTC_WAKEUP) {
523cf69771bSopenharmony_ci        auto systemTimeNow = system_clock::now().time_since_epoch();
524cf69771bSopenharmony_ci        auto offset = when - systemTimeNow;
525cf69771bSopenharmony_ci        TIME_HILOGD(TIME_MODULE_SERVICE, "systemTimeNow : %{public}lld offset : %{public}lld",
526cf69771bSopenharmony_ci                    systemTimeNow.count(), offset.count());
527cf69771bSopenharmony_ci        if (offset.count() <= 0) {
528cf69771bSopenharmony_ci            return bootTimePoint;
529cf69771bSopenharmony_ci        } else {
530cf69771bSopenharmony_ci            return bootTimePoint + offset;
531cf69771bSopenharmony_ci        }
532cf69771bSopenharmony_ci    }
533cf69771bSopenharmony_ci    auto bootTimeNow = bootTimePoint.time_since_epoch();
534cf69771bSopenharmony_ci    auto offset = when - bootTimeNow;
535cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "bootTimeNow : %{public}lld offset : %{public}lld",
536cf69771bSopenharmony_ci                bootTimeNow.count(), offset.count());
537cf69771bSopenharmony_ci    if (offset.count() <= 0) {
538cf69771bSopenharmony_ci        return bootTimePoint;
539cf69771bSopenharmony_ci    } else {
540cf69771bSopenharmony_ci        return bootTimePoint + offset;
541cf69771bSopenharmony_ci    }
542cf69771bSopenharmony_ci}
543cf69771bSopenharmony_ci
544cf69771bSopenharmony_civoid TimerManager::TimerLooper()
545cf69771bSopenharmony_ci{
546cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "Start timer wait loop");
547cf69771bSopenharmony_ci    pthread_setname_np(pthread_self(), "timer_loop");
548cf69771bSopenharmony_ci    std::vector<std::shared_ptr<TimerInfo>> triggerList;
549cf69771bSopenharmony_ci    while (runFlag_) {
550cf69771bSopenharmony_ci        uint32_t result = handler_->WaitForAlarm();
551cf69771bSopenharmony_ci        auto nowRtc = std::chrono::system_clock::now();
552cf69771bSopenharmony_ci        auto nowElapsed = GetBootTimeNs();
553cf69771bSopenharmony_ci        triggerList.clear();
554cf69771bSopenharmony_ci
555cf69771bSopenharmony_ci        if ((result & TIME_CHANGED_MASK) != 0) {
556cf69771bSopenharmony_ci            TIME_HILOGI(TIME_MODULE_SERVICE, "ret: %{public}u", result);
557cf69771bSopenharmony_ci            system_clock::time_point lastTimeChangeClockTime;
558cf69771bSopenharmony_ci            system_clock::time_point expectedClockTime;
559cf69771bSopenharmony_ci            std::lock_guard<std::mutex> lock(mutex_);
560cf69771bSopenharmony_ci            lastTimeChangeClockTime = lastTimeChangeClockTime_;
561cf69771bSopenharmony_ci            expectedClockTime = lastTimeChangeClockTime +
562cf69771bSopenharmony_ci                (duration_cast<milliseconds>(nowElapsed.time_since_epoch()) -
563cf69771bSopenharmony_ci                duration_cast<milliseconds>(lastTimeChangeRealtime_.time_since_epoch()));
564cf69771bSopenharmony_ci            if (lastTimeChangeClockTime == system_clock::time_point::min()
565cf69771bSopenharmony_ci                || nowRtc < expectedClockTime
566cf69771bSopenharmony_ci                || nowRtc > (expectedClockTime + milliseconds(ONE_THOUSAND))) {
567cf69771bSopenharmony_ci                ReBatchAllTimers();
568cf69771bSopenharmony_ci                lastTimeChangeClockTime_ = nowRtc;
569cf69771bSopenharmony_ci                lastTimeChangeRealtime_ = nowElapsed;
570cf69771bSopenharmony_ci            }
571cf69771bSopenharmony_ci        }
572cf69771bSopenharmony_ci
573cf69771bSopenharmony_ci        if (result != TIME_CHANGED_MASK) {
574cf69771bSopenharmony_ci            {
575cf69771bSopenharmony_ci                std::lock_guard<std::mutex> lock(mutex_);
576cf69771bSopenharmony_ci                TriggerTimersLocked(triggerList, nowElapsed);
577cf69771bSopenharmony_ci            }
578cf69771bSopenharmony_ci            // in this function, timeservice apply a runninglock from powermanager
579cf69771bSopenharmony_ci            // release mutex to prevent powermanager from using the interface of timeservice
580cf69771bSopenharmony_ci            // which may cause deadlock
581cf69771bSopenharmony_ci            DeliverTimersLocked(triggerList);
582cf69771bSopenharmony_ci            {
583cf69771bSopenharmony_ci                std::lock_guard<std::mutex> lock(mutex_);
584cf69771bSopenharmony_ci                RescheduleKernelTimerLocked();
585cf69771bSopenharmony_ci            }
586cf69771bSopenharmony_ci        }
587cf69771bSopenharmony_ci    }
588cf69771bSopenharmony_ci}
589cf69771bSopenharmony_ci
590cf69771bSopenharmony_ciTimerManager::~TimerManager()
591cf69771bSopenharmony_ci{
592cf69771bSopenharmony_ci    if (alarmThread_ && alarmThread_->joinable()) {
593cf69771bSopenharmony_ci        runFlag_ = false;
594cf69771bSopenharmony_ci        alarmThread_->join();
595cf69771bSopenharmony_ci    }
596cf69771bSopenharmony_ci}
597cf69771bSopenharmony_ci
598cf69771bSopenharmony_cisteady_clock::time_point TimerManager::GetBootTimeNs()
599cf69771bSopenharmony_ci{
600cf69771bSopenharmony_ci    int64_t timeNow = -1;
601cf69771bSopenharmony_ci    struct timespec tv {};
602cf69771bSopenharmony_ci    if (clock_gettime(CLOCK_BOOTTIME, &tv) < 0) {
603cf69771bSopenharmony_ci        return steady_clock::now();
604cf69771bSopenharmony_ci    }
605cf69771bSopenharmony_ci    timeNow = tv.tv_sec * NANO_TO_SECOND + tv.tv_nsec;
606cf69771bSopenharmony_ci    steady_clock::time_point tp_epoch ((nanoseconds(timeNow)));
607cf69771bSopenharmony_ci    return tp_epoch;
608cf69771bSopenharmony_ci}
609cf69771bSopenharmony_ci
610cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
611cf69771bSopenharmony_civoid TimerManager::TriggerIdleTimer()
612cf69771bSopenharmony_ci{
613cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE, "Idle alarm triggers.");
614cf69771bSopenharmony_ci    mPendingIdleUntil_ = nullptr;
615cf69771bSopenharmony_ci    delayedTimers_.clear();
616cf69771bSopenharmony_ci    std::for_each(pendingDelayTimers_.begin(), pendingDelayTimers_.end(),
617cf69771bSopenharmony_ci        [this](const std::shared_ptr<TimerInfo> &pendingTimer) {
618cf69771bSopenharmony_ci            TIME_HILOGI(TIME_MODULE_SERVICE, "Set timer from delay list, id=%{public}" PRId64 "", pendingTimer->id);
619cf69771bSopenharmony_ci            if (pendingTimer->whenElapsed > GetBootTimeNs()) {
620cf69771bSopenharmony_ci                pendingTimer->UpdateWhenElapsedFromNow(GetBootTimeNs(), pendingTimer->offset);
621cf69771bSopenharmony_ci            } else {
622cf69771bSopenharmony_ci                // 2 means the time of performing task.
623cf69771bSopenharmony_ci                pendingTimer->UpdateWhenElapsedFromNow(GetBootTimeNs(), milliseconds(2));
624cf69771bSopenharmony_ci            }
625cf69771bSopenharmony_ci            SetHandlerLocked(pendingTimer, false, false);
626cf69771bSopenharmony_ci        });
627cf69771bSopenharmony_ci    pendingDelayTimers_.clear();
628cf69771bSopenharmony_ci    ReBatchAllTimers();
629cf69771bSopenharmony_ci}
630cf69771bSopenharmony_ci
631cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
632cf69771bSopenharmony_cibool TimerManager::ProcTriggerTimer(std::shared_ptr<TimerInfo> &alarm,
633cf69771bSopenharmony_ci                                    const std::chrono::steady_clock::time_point &nowElapsed)
634cf69771bSopenharmony_ci{
635cf69771bSopenharmony_ci    if (mPendingIdleUntil_ != nullptr && mPendingIdleUntil_->id == alarm->id) {
636cf69771bSopenharmony_ci        TriggerIdleTimer();
637cf69771bSopenharmony_ci    }
638cf69771bSopenharmony_ci    if (TimerProxy::GetInstance().IsUidProxy(alarm->uid)) {
639cf69771bSopenharmony_ci        alarm->UpdateWhenElapsedFromNow(nowElapsed, milliseconds(TimerProxy::GetInstance().GetProxyDelayTime()));
640cf69771bSopenharmony_ci        TIME_HILOGD(TIME_MODULE_SERVICE, "UpdateWhenElapsed for proxy timer trigger. "
641cf69771bSopenharmony_ci            "uid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
642cf69771bSopenharmony_ci            alarm->uid, alarm->id, alarm->whenElapsed.time_since_epoch().count(),
643cf69771bSopenharmony_ci            nowElapsed.time_since_epoch().count());
644cf69771bSopenharmony_ci        SetHandlerLocked(alarm, false, false);
645cf69771bSopenharmony_ci        return false;
646cf69771bSopenharmony_ci    } else if (TimerProxy::GetInstance().IsPidProxy(alarm->pid)) {
647cf69771bSopenharmony_ci        alarm->UpdateWhenElapsedFromNow(nowElapsed, milliseconds(TimerProxy::GetInstance().GetProxyDelayTime()));
648cf69771bSopenharmony_ci        TIME_HILOGD(TIME_MODULE_SERVICE, "UpdateWhenElapsed for proxy timer trigger. "
649cf69771bSopenharmony_ci            "pid= %{public}d, id=%{public}" PRId64 ", timer whenElapsed=%{public}lld, now=%{public}lld",
650cf69771bSopenharmony_ci            alarm->pid, alarm->id, alarm->whenElapsed.time_since_epoch().count(),
651cf69771bSopenharmony_ci            nowElapsed.time_since_epoch().count());
652cf69771bSopenharmony_ci        SetHandlerLocked(alarm, false, false);
653cf69771bSopenharmony_ci        return false;
654cf69771bSopenharmony_ci    } else {
655cf69771bSopenharmony_ci        HandleRepeatTimer(alarm, nowElapsed);
656cf69771bSopenharmony_ci        return true;
657cf69771bSopenharmony_ci    }
658cf69771bSopenharmony_ci}
659cf69771bSopenharmony_ci
660cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
661cf69771bSopenharmony_cibool TimerManager::TriggerTimersLocked(std::vector<std::shared_ptr<TimerInfo>> &triggerList,
662cf69771bSopenharmony_ci                                       std::chrono::steady_clock::time_point nowElapsed)
663cf69771bSopenharmony_ci{
664cf69771bSopenharmony_ci    bool hasWakeup = false;
665cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "current time %{public}lld", GetBootTimeNs().time_since_epoch().count());
666cf69771bSopenharmony_ci
667cf69771bSopenharmony_ci    for (auto iter = alarmBatches_.begin(); iter != alarmBatches_.end();) {
668cf69771bSopenharmony_ci        if (*iter == nullptr) {
669cf69771bSopenharmony_ci            TIME_HILOGE(TIME_MODULE_SERVICE, "alarmBatches_ has nullptr");
670cf69771bSopenharmony_ci            iter = alarmBatches_.erase(iter);
671cf69771bSopenharmony_ci            continue;
672cf69771bSopenharmony_ci        }
673cf69771bSopenharmony_ci        if ((*iter)->GetStart() > nowElapsed) {
674cf69771bSopenharmony_ci            ++iter;
675cf69771bSopenharmony_ci            continue;
676cf69771bSopenharmony_ci        }
677cf69771bSopenharmony_ci        auto batch = *iter;
678cf69771bSopenharmony_ci        iter = alarmBatches_.erase(iter);
679cf69771bSopenharmony_ci        TIME_HILOGD(
680cf69771bSopenharmony_ci            TIME_MODULE_SERVICE, "batch size= %{public}d", static_cast<int>(alarmBatches_.size()));
681cf69771bSopenharmony_ci        const auto n = batch->Size();
682cf69771bSopenharmony_ci        for (unsigned int i = 0; i < n; ++i) {
683cf69771bSopenharmony_ci            auto alarm = batch->Get(i);
684cf69771bSopenharmony_ci            triggerList.push_back(alarm);
685cf69771bSopenharmony_ci            TIME_SIMPLIFY_HILOGI(TIME_MODULE_SERVICE, "uid: %{public}d id:%{public}" PRId64 " name:%{public}s"
686cf69771bSopenharmony_ci                " wk:%{public}u",
687cf69771bSopenharmony_ci                alarm->uid, alarm->id, alarm->bundleName.c_str(), alarm->wakeup);
688cf69771bSopenharmony_ci
689cf69771bSopenharmony_ci            if (alarm->wakeup) {
690cf69771bSopenharmony_ci                hasWakeup = true;
691cf69771bSopenharmony_ci            }
692cf69771bSopenharmony_ci        }
693cf69771bSopenharmony_ci    }
694cf69771bSopenharmony_ci    for (auto iter = triggerList.begin(); iter != triggerList.end();) {
695cf69771bSopenharmony_ci        auto alarm = *iter;
696cf69771bSopenharmony_ci        if (!ProcTriggerTimer(alarm, nowElapsed)) {
697cf69771bSopenharmony_ci            iter = triggerList.erase(iter);
698cf69771bSopenharmony_ci        } else {
699cf69771bSopenharmony_ci            ++iter;
700cf69771bSopenharmony_ci        }
701cf69771bSopenharmony_ci    }
702cf69771bSopenharmony_ci
703cf69771bSopenharmony_ci    std::sort(triggerList.begin(), triggerList.end(),
704cf69771bSopenharmony_ci        [](const std::shared_ptr<TimerInfo> &l, const std::shared_ptr<TimerInfo> &r) {
705cf69771bSopenharmony_ci            return l->whenElapsed < r->whenElapsed;
706cf69771bSopenharmony_ci        });
707cf69771bSopenharmony_ci
708cf69771bSopenharmony_ci    return hasWakeup;
709cf69771bSopenharmony_ci}
710cf69771bSopenharmony_ci
711cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
712cf69771bSopenharmony_civoid TimerManager::RescheduleKernelTimerLocked()
713cf69771bSopenharmony_ci{
714cf69771bSopenharmony_ci    auto nextNonWakeup = std::chrono::steady_clock::time_point::min();
715cf69771bSopenharmony_ci    auto bootTime = GetBootTimeNs();
716cf69771bSopenharmony_ci    if (!alarmBatches_.empty()) {
717cf69771bSopenharmony_ci        auto firstWakeup = FindFirstWakeupBatchLocked();
718cf69771bSopenharmony_ci        auto firstBatch = alarmBatches_.front();
719cf69771bSopenharmony_ci        if (firstWakeup != nullptr) {
720cf69771bSopenharmony_ci            #ifdef POWER_MANAGER_ENABLE
721cf69771bSopenharmony_ci            HandleRunningLock(firstWakeup);
722cf69771bSopenharmony_ci            #endif
723cf69771bSopenharmony_ci            SetLocked(ELAPSED_REALTIME_WAKEUP, firstWakeup->GetStart().time_since_epoch(), bootTime);
724cf69771bSopenharmony_ci        }
725cf69771bSopenharmony_ci        if (firstBatch != firstWakeup) {
726cf69771bSopenharmony_ci            nextNonWakeup = firstBatch->GetStart();
727cf69771bSopenharmony_ci        }
728cf69771bSopenharmony_ci    }
729cf69771bSopenharmony_ci
730cf69771bSopenharmony_ci    if (nextNonWakeup != std::chrono::steady_clock::time_point::min()) {
731cf69771bSopenharmony_ci        SetLocked(ELAPSED_REALTIME, nextNonWakeup.time_since_epoch(), bootTime);
732cf69771bSopenharmony_ci    }
733cf69771bSopenharmony_ci}
734cf69771bSopenharmony_ci
735cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
736cf69771bSopenharmony_cistd::shared_ptr<Batch> TimerManager::FindFirstWakeupBatchLocked()
737cf69771bSopenharmony_ci{
738cf69771bSopenharmony_ci    auto it = std::find_if(alarmBatches_.begin(),
739cf69771bSopenharmony_ci                           alarmBatches_.end(),
740cf69771bSopenharmony_ci                           [](const std::shared_ptr<Batch> &batch) {
741cf69771bSopenharmony_ci                               return batch->HasWakeups();
742cf69771bSopenharmony_ci                           });
743cf69771bSopenharmony_ci    return (it != alarmBatches_.end()) ? *it : nullptr;
744cf69771bSopenharmony_ci}
745cf69771bSopenharmony_ci
746cf69771bSopenharmony_civoid TimerManager::SetLocked(int type, std::chrono::nanoseconds when, std::chrono::steady_clock::time_point bootTime)
747cf69771bSopenharmony_ci{
748cf69771bSopenharmony_ci    handler_->Set(static_cast<uint32_t>(type), when, bootTime);
749cf69771bSopenharmony_ci}
750cf69771bSopenharmony_ci
751cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
752cf69771bSopenharmony_civoid TimerManager::InsertAndBatchTimerLocked(std::shared_ptr<TimerInfo> alarm)
753cf69771bSopenharmony_ci{
754cf69771bSopenharmony_ci    int64_t whichBatch = (alarm->flags & static_cast<uint32_t>(STANDALONE)) ?
755cf69771bSopenharmony_ci                         -1 :
756cf69771bSopenharmony_ci                         AttemptCoalesceLocked(alarm->whenElapsed, alarm->maxWhenElapsed);
757cf69771bSopenharmony_ci    TIME_SIMPLIFY_HILOGI(TIME_MODULE_SERVICE, "bat: %{public}" PRId64 " id:%{public}" PRIu64 " "
758cf69771bSopenharmony_ci                         "we:%{public}lld mwe:%{public}lld",
759cf69771bSopenharmony_ci                         whichBatch, alarm->id, alarm->whenElapsed.time_since_epoch().count(),
760cf69771bSopenharmony_ci                         alarm->maxWhenElapsed.time_since_epoch().count());
761cf69771bSopenharmony_ci    if (whichBatch < 0) {
762cf69771bSopenharmony_ci        AddBatchLocked(alarmBatches_, std::make_shared<Batch>(*alarm));
763cf69771bSopenharmony_ci    } else {
764cf69771bSopenharmony_ci        auto batch = alarmBatches_.at(whichBatch);
765cf69771bSopenharmony_ci        if (batch->Add(alarm)) {
766cf69771bSopenharmony_ci            alarmBatches_.erase(alarmBatches_.begin() + whichBatch);
767cf69771bSopenharmony_ci            AddBatchLocked(alarmBatches_, batch);
768cf69771bSopenharmony_ci        }
769cf69771bSopenharmony_ci    }
770cf69771bSopenharmony_ci}
771cf69771bSopenharmony_ci
772cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
773cf69771bSopenharmony_ciint64_t TimerManager::AttemptCoalesceLocked(std::chrono::steady_clock::time_point whenElapsed,
774cf69771bSopenharmony_ci                                            std::chrono::steady_clock::time_point maxWhen)
775cf69771bSopenharmony_ci{
776cf69771bSopenharmony_ci    auto it = std::find_if(alarmBatches_.begin(), alarmBatches_.end(),
777cf69771bSopenharmony_ci        [whenElapsed, maxWhen](const std::shared_ptr<Batch> &batch) {
778cf69771bSopenharmony_ci            return (batch->GetFlags() & static_cast<uint32_t>(STANDALONE)) == 0 &&
779cf69771bSopenharmony_ci                   (batch->CanHold(whenElapsed, maxWhen));
780cf69771bSopenharmony_ci        });
781cf69771bSopenharmony_ci    if (it != alarmBatches_.end()) {
782cf69771bSopenharmony_ci        return std::distance(alarmBatches_.begin(), it);
783cf69771bSopenharmony_ci    }
784cf69771bSopenharmony_ci    return -1;
785cf69771bSopenharmony_ci}
786cf69771bSopenharmony_ci
787cf69771bSopenharmony_civoid TimerManager::NotifyWantAgentRetry(std::shared_ptr<TimerInfo> timer)
788cf69771bSopenharmony_ci{
789cf69771bSopenharmony_ci    auto retryRegister = [timer]() {
790cf69771bSopenharmony_ci        for (int i = 0; i < WANT_RETRY_TIMES; i++) {
791cf69771bSopenharmony_ci            sleep(WANT_RETRY_INTERVAL << i);
792cf69771bSopenharmony_ci            if (TimerManager::GetInstance()->NotifyWantAgent(timer)) {
793cf69771bSopenharmony_ci                return;
794cf69771bSopenharmony_ci            }
795cf69771bSopenharmony_ci        }
796cf69771bSopenharmony_ci    };
797cf69771bSopenharmony_ci    std::thread thread(retryRegister);
798cf69771bSopenharmony_ci    thread.detach();
799cf69771bSopenharmony_ci}
800cf69771bSopenharmony_ci
801cf69771bSopenharmony_ciint32_t TimerManager::CheckUserIdForNotify(const std::shared_ptr<TimerInfo> &timer)
802cf69771bSopenharmony_ci{
803cf69771bSopenharmony_ci    int userIdOfTimer = -1;
804cf69771bSopenharmony_ci    int foregroundUserId = -1;
805cf69771bSopenharmony_ci    int getLocalIdErr = AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(timer->uid, userIdOfTimer);
806cf69771bSopenharmony_ci    if (getLocalIdErr != ERR_OK) {
807cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "Get account id from uid failed, errcode: %{public}d", getLocalIdErr);
808cf69771bSopenharmony_ci        return E_TIME_ACCOUNT_ERROR;
809cf69771bSopenharmony_ci    }
810cf69771bSopenharmony_ci    int getForegroundIdErr = AccountSA::OsAccountManager::GetForegroundOsAccountLocalId(foregroundUserId);
811cf69771bSopenharmony_ci    if (getForegroundIdErr != ERR_OK) {
812cf69771bSopenharmony_ci        TIME_HILOGE(TIME_MODULE_SERVICE, "Get foreground account id failed, errcode: %{public}d", getForegroundIdErr);
813cf69771bSopenharmony_ci        return E_TIME_ACCOUNT_ERROR;
814cf69771bSopenharmony_ci    }
815cf69771bSopenharmony_ci    if (userIdOfTimer == foregroundUserId || userIdOfTimer == SYSTEM_USER_ID) {
816cf69771bSopenharmony_ci        return E_TIME_OK;
817cf69771bSopenharmony_ci    } else {
818cf69771bSopenharmony_ci        TIME_HILOGI(TIME_MODULE_SERVICE, "WA wait switch user, uid: %{public}d, timerId: %{public}" PRId64,
819cf69771bSopenharmony_ci            timer->uid, timer->id);
820cf69771bSopenharmony_ci        return E_TIME_ACCOUNT_NOT_MATCH;
821cf69771bSopenharmony_ci    }
822cf69771bSopenharmony_ci}
823cf69771bSopenharmony_ci
824cf69771bSopenharmony_civoid TimerManager::DeliverTimersLocked(const std::vector<std::shared_ptr<TimerInfo>> &triggerList)
825cf69771bSopenharmony_ci{
826cf69771bSopenharmony_ci    auto wakeupNums = std::count_if(triggerList.begin(), triggerList.end(), [](auto timer) {return timer->wakeup;});
827cf69771bSopenharmony_ci    for (const auto &timer : triggerList) {
828cf69771bSopenharmony_ci        if (timer->wakeup) {
829cf69771bSopenharmony_ci            #ifdef POWER_MANAGER_ENABLE
830cf69771bSopenharmony_ci            TIME_HILOGD(TIME_MODULE_SERVICE, "id: %{public}" PRId64 ", uid: %{public}d bundleName: %{public}s",
831cf69771bSopenharmony_ci                        timer->id, timer->uid, timer->bundleName.c_str());
832cf69771bSopenharmony_ci            AddRunningLock(USE_LOCK_ONE_SEC_IN_NANO);
833cf69771bSopenharmony_ci            #endif
834cf69771bSopenharmony_ci            StatisticReporter(IPCSkeleton::GetCallingPid(), wakeupNums, timer);
835cf69771bSopenharmony_ci        }
836cf69771bSopenharmony_ci        if (timer->callback) {
837cf69771bSopenharmony_ci            if (TimerProxy::GetInstance().CallbackAlarmIfNeed(timer) == PEER_END_DEAD
838cf69771bSopenharmony_ci                && !timer->wantAgent) {
839cf69771bSopenharmony_ci                DestroyTimer(timer->id);
840cf69771bSopenharmony_ci                continue;
841cf69771bSopenharmony_ci            }
842cf69771bSopenharmony_ci        }
843cf69771bSopenharmony_ci        if (timer->wantAgent) {
844cf69771bSopenharmony_ci            if (!NotifyWantAgent(timer) && CheckNeedRecoverOnReboot(timer->bundleName, timer->type)) {
845cf69771bSopenharmony_ci                NotifyWantAgentRetry(timer);
846cf69771bSopenharmony_ci            }
847cf69771bSopenharmony_ci            if (CheckNeedRecoverOnReboot(timer->bundleName, timer->type)) {
848cf69771bSopenharmony_ci                OHOS::NativeRdb::ValuesBucket values;
849cf69771bSopenharmony_ci                values.PutInt("state", 0);
850cf69771bSopenharmony_ci                OHOS::NativeRdb::RdbPredicates rdbPredicates(HOLD_ON_REBOOT);
851cf69771bSopenharmony_ci                rdbPredicates.EqualTo("state", 1)
852cf69771bSopenharmony_ci                    ->And()
853cf69771bSopenharmony_ci                    ->EqualTo("timerId", static_cast<int64_t>(timer->id));
854cf69771bSopenharmony_ci                TimeDatabase::GetInstance().Update(values, rdbPredicates);
855cf69771bSopenharmony_ci            } else {
856cf69771bSopenharmony_ci                OHOS::NativeRdb::ValuesBucket values;
857cf69771bSopenharmony_ci                values.PutInt("state", 0);
858cf69771bSopenharmony_ci                OHOS::NativeRdb::RdbPredicates rdbPredicates(DROP_ON_REBOOT);
859cf69771bSopenharmony_ci                rdbPredicates.EqualTo("state", 1)
860cf69771bSopenharmony_ci                    ->And()
861cf69771bSopenharmony_ci                    ->EqualTo("timerId", static_cast<int64_t>(timer->id));
862cf69771bSopenharmony_ci                TimeDatabase::GetInstance().Update(values, rdbPredicates);
863cf69771bSopenharmony_ci            }
864cf69771bSopenharmony_ci        }
865cf69771bSopenharmony_ci        if (((timer->flags & static_cast<uint32_t>(IS_DISPOSABLE)) > 0) &&
866cf69771bSopenharmony_ci            (timer->repeatInterval == milliseconds::zero())) {
867cf69771bSopenharmony_ci            DestroyTimer(timer->id);
868cf69771bSopenharmony_ci        }
869cf69771bSopenharmony_ci    }
870cf69771bSopenharmony_ci}
871cf69771bSopenharmony_ci
872cf69771bSopenharmony_cibool TimerManager::NotifyWantAgent(const std::shared_ptr<TimerInfo> &timer)
873cf69771bSopenharmony_ci{
874cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "trigger wantAgent.");
875cf69771bSopenharmony_ci    auto wantAgent = timer->wantAgent;
876cf69771bSopenharmony_ci    std::shared_ptr<AAFwk::Want> want = OHOS::AbilityRuntime::WantAgent::WantAgentHelper::GetWant(wantAgent);
877cf69771bSopenharmony_ci    if (want == nullptr) {
878cf69771bSopenharmony_ci        switch (CheckUserIdForNotify(timer)) {
879cf69771bSopenharmony_ci            case E_TIME_ACCOUNT_NOT_MATCH:
880cf69771bSopenharmony_ci                // No need to retry.
881cf69771bSopenharmony_ci                return true;
882cf69771bSopenharmony_ci            case E_TIME_ACCOUNT_ERROR:
883cf69771bSopenharmony_ci                TIME_HILOGE(TIME_MODULE_SERVICE, "want is nullptr, id=%{public}" PRId64 "", timer->id);
884cf69771bSopenharmony_ci                return false;
885cf69771bSopenharmony_ci            default:
886cf69771bSopenharmony_ci                break;
887cf69771bSopenharmony_ci        }
888cf69771bSopenharmony_ci        auto database = TimeDatabase::GetInstance();
889cf69771bSopenharmony_ci        OHOS::NativeRdb::RdbPredicates holdRdbPredicates(HOLD_ON_REBOOT);
890cf69771bSopenharmony_ci        holdRdbPredicates.EqualTo("timerId", static_cast<int64_t>(timer->id));
891cf69771bSopenharmony_ci        auto holdResultSet = database.Query(holdRdbPredicates, ALL_DATA);
892cf69771bSopenharmony_ci        if (holdResultSet == nullptr || holdResultSet->GoToFirstRow() != OHOS::NativeRdb::E_OK) {
893cf69771bSopenharmony_ci            TIME_HILOGE(TIME_MODULE_SERVICE, "db query failed nullptr");
894cf69771bSopenharmony_ci            if (holdResultSet != nullptr) {
895cf69771bSopenharmony_ci                holdResultSet->Close();
896cf69771bSopenharmony_ci            }
897cf69771bSopenharmony_ci            return false;
898cf69771bSopenharmony_ci        }
899cf69771bSopenharmony_ci        // Line 7 is 'wantAgent'
900cf69771bSopenharmony_ci        wantAgent = OHOS::AbilityRuntime::WantAgent::WantAgentHelper::FromString(GetString(holdResultSet, 7));
901cf69771bSopenharmony_ci        holdResultSet->Close();
902cf69771bSopenharmony_ci        switch (CheckUserIdForNotify(timer)) {
903cf69771bSopenharmony_ci            case E_TIME_ACCOUNT_NOT_MATCH:
904cf69771bSopenharmony_ci                TIME_HILOGI(TIME_MODULE_SERVICE, "user sw after FS, id=%{public}" PRId64 "", timer->id);
905cf69771bSopenharmony_ci                // No need to retry.
906cf69771bSopenharmony_ci                return true;
907cf69771bSopenharmony_ci            case E_TIME_ACCOUNT_ERROR:
908cf69771bSopenharmony_ci                TIME_HILOGE(TIME_MODULE_SERVICE, "want is nullptr, id=%{public}" PRId64 "", timer->id);
909cf69771bSopenharmony_ci                return false;
910cf69771bSopenharmony_ci            default:
911cf69771bSopenharmony_ci                break;
912cf69771bSopenharmony_ci        }
913cf69771bSopenharmony_ci        want = OHOS::AbilityRuntime::WantAgent::WantAgentHelper::GetWant(wantAgent);
914cf69771bSopenharmony_ci        if (want == nullptr) {
915cf69771bSopenharmony_ci            TIME_HILOGE(TIME_MODULE_SERVICE, "want is nullptr, id=%{public}" PRId64 "", timer->id);
916cf69771bSopenharmony_ci            return false;
917cf69771bSopenharmony_ci        }
918cf69771bSopenharmony_ci    }
919cf69771bSopenharmony_ci    OHOS::AbilityRuntime::WantAgent::TriggerInfo paramsInfo("", nullptr, want, WANTAGENT_CODE_ELEVEN);
920cf69771bSopenharmony_ci    auto code = AbilityRuntime::WantAgent::WantAgentHelper::TriggerWantAgent(wantAgent, nullptr, paramsInfo);
921cf69771bSopenharmony_ci    TIME_SIMPLIFY_HILOGI(TIME_MODULE_SERVICE, "trigWA ret: %{public}d", code);
922cf69771bSopenharmony_ci    return code == ERR_OK;
923cf69771bSopenharmony_ci}
924cf69771bSopenharmony_ci
925cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
926cf69771bSopenharmony_civoid TimerManager::UpdateTimersState(std::shared_ptr<TimerInfo> &alarm)
927cf69771bSopenharmony_ci{
928cf69771bSopenharmony_ci    RemoveLocked(alarm->id, false);
929cf69771bSopenharmony_ci    AdjustSingleTimer(alarm);
930cf69771bSopenharmony_ci    InsertAndBatchTimerLocked(alarm);
931cf69771bSopenharmony_ci    RescheduleKernelTimerLocked();
932cf69771bSopenharmony_ci}
933cf69771bSopenharmony_ci
934cf69771bSopenharmony_cibool TimerManager::ProxyTimer(int32_t uid, bool isProxy, bool needRetrigger)
935cf69771bSopenharmony_ci{
936cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
937cf69771bSopenharmony_ci    return TimerProxy::GetInstance().ProxyTimer(uid, isProxy, needRetrigger, GetBootTimeNs(),
938cf69771bSopenharmony_ci        [this] (std::shared_ptr<TimerInfo> &alarm) { UpdateTimersState(alarm); });
939cf69771bSopenharmony_ci}
940cf69771bSopenharmony_ci
941cf69771bSopenharmony_cibool TimerManager::AdjustTimer(bool isAdjust, uint32_t interval)
942cf69771bSopenharmony_ci{
943cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
944cf69771bSopenharmony_ci    if (adjustPolicy_ == isAdjust && adjustInterval_ == interval) {
945cf69771bSopenharmony_ci        TIME_HILOGI(TIME_MODULE_SERVICE, "already deal timer adjust, flag: %{public}d", isAdjust);
946cf69771bSopenharmony_ci        return false;
947cf69771bSopenharmony_ci    }
948cf69771bSopenharmony_ci    std::chrono::steady_clock::time_point now = GetBootTimeNs();
949cf69771bSopenharmony_ci    adjustPolicy_ = isAdjust;
950cf69771bSopenharmony_ci    adjustInterval_ = interval;
951cf69771bSopenharmony_ci    auto callback = [this] (AdjustTimerCallback adjustTimer) {
952cf69771bSopenharmony_ci        bool isChanged = false;
953cf69771bSopenharmony_ci        auto nowElapsed = GetBootTimeNs();
954cf69771bSopenharmony_ci        for (const auto &batch : alarmBatches_) {
955cf69771bSopenharmony_ci            if (!batch) {
956cf69771bSopenharmony_ci                continue;
957cf69771bSopenharmony_ci            }
958cf69771bSopenharmony_ci            auto n = batch->Size();
959cf69771bSopenharmony_ci            for (unsigned int i = 0; i < n; i++) {
960cf69771bSopenharmony_ci                auto timer = batch->Get(i);
961cf69771bSopenharmony_ci                ReCalcuOriWhenElapsed(timer, nowElapsed);
962cf69771bSopenharmony_ci                isChanged = adjustTimer(timer) || isChanged;
963cf69771bSopenharmony_ci            }
964cf69771bSopenharmony_ci        }
965cf69771bSopenharmony_ci        if (isChanged) {
966cf69771bSopenharmony_ci            TIME_HILOGI(TIME_MODULE_SERVICE, "timer adjust executing, policy: %{public}d", adjustPolicy_);
967cf69771bSopenharmony_ci            ReBatchAllTimers();
968cf69771bSopenharmony_ci        }
969cf69771bSopenharmony_ci    };
970cf69771bSopenharmony_ci
971cf69771bSopenharmony_ci    return TimerProxy::GetInstance().AdjustTimer(isAdjust, interval, now, callback);
972cf69771bSopenharmony_ci}
973cf69771bSopenharmony_ci
974cf69771bSopenharmony_cibool TimerManager::ProxyTimer(std::set<int> pidList, bool isProxy, bool needRetrigger)
975cf69771bSopenharmony_ci{
976cf69771bSopenharmony_ci    std::set<int> failurePid;
977cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
978cf69771bSopenharmony_ci    for (std::set<int>::iterator pid = pidList.begin(); pid != pidList.end(); ++pid) {
979cf69771bSopenharmony_ci        if (!TimerProxy::GetInstance().PidProxyTimer(*pid, isProxy, needRetrigger, GetBootTimeNs(),
980cf69771bSopenharmony_ci            [this] (std::shared_ptr<TimerInfo> &alarm) { UpdateTimersState(alarm); })) {
981cf69771bSopenharmony_ci            failurePid.insert(*pid);
982cf69771bSopenharmony_ci        }
983cf69771bSopenharmony_ci    }
984cf69771bSopenharmony_ci    return (failurePid.size() == 0);
985cf69771bSopenharmony_ci}
986cf69771bSopenharmony_ci
987cf69771bSopenharmony_civoid TimerManager::ReCalcuOriWhenElapsed(std::shared_ptr<TimerInfo> timer,
988cf69771bSopenharmony_ci                                         std::chrono::steady_clock::time_point nowElapsed)
989cf69771bSopenharmony_ci{
990cf69771bSopenharmony_ci    if (adjustPolicy_) {
991cf69771bSopenharmony_ci        return;
992cf69771bSopenharmony_ci    }
993cf69771bSopenharmony_ci    auto whenElapsed = ConvertToElapsed(timer->origWhen, timer->type);
994cf69771bSopenharmony_ci    steady_clock::time_point maxElapsed;
995cf69771bSopenharmony_ci    if (timer->windowLength == milliseconds::zero()) {
996cf69771bSopenharmony_ci        maxElapsed = whenElapsed;
997cf69771bSopenharmony_ci    } else {
998cf69771bSopenharmony_ci        maxElapsed = (timer->windowLength > milliseconds::zero()) ?
999cf69771bSopenharmony_ci                     (whenElapsed + timer->windowLength) :
1000cf69771bSopenharmony_ci                     MaxTriggerTime(nowElapsed, whenElapsed, timer->repeatInterval);
1001cf69771bSopenharmony_ci    }
1002cf69771bSopenharmony_ci    timer->originWhenElapsed = whenElapsed;
1003cf69771bSopenharmony_ci    timer->originMaxWhenElapsed = maxElapsed;
1004cf69771bSopenharmony_ci}
1005cf69771bSopenharmony_ci
1006cf69771bSopenharmony_civoid TimerManager::SetTimerExemption(const std::unordered_set<std::string> &nameArr, bool isExemption)
1007cf69771bSopenharmony_ci{
1008cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
1009cf69771bSopenharmony_ci    TimerProxy::GetInstance().SetTimerExemption(nameArr, isExemption);
1010cf69771bSopenharmony_ci}
1011cf69771bSopenharmony_ci
1012cf69771bSopenharmony_cibool TimerManager::AdjustSingleTimer(std::shared_ptr<TimerInfo> timer)
1013cf69771bSopenharmony_ci{
1014cf69771bSopenharmony_ci    if (!adjustPolicy_) {
1015cf69771bSopenharmony_ci        return false;
1016cf69771bSopenharmony_ci    }
1017cf69771bSopenharmony_ci    return TimerProxy::GetInstance().AdjustTimer(adjustPolicy_, adjustInterval_, GetBootTimeNs(),
1018cf69771bSopenharmony_ci        [this, timer] (AdjustTimerCallback adjustTimer) { adjustTimer(timer); });
1019cf69771bSopenharmony_ci}
1020cf69771bSopenharmony_ci
1021cf69771bSopenharmony_cibool TimerManager::ResetAllProxy()
1022cf69771bSopenharmony_ci{
1023cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
1024cf69771bSopenharmony_ci    return TimerProxy::GetInstance().ResetAllProxy(GetBootTimeNs(),
1025cf69771bSopenharmony_ci        [this] (std::shared_ptr<TimerInfo> &alarm) { UpdateTimersState(alarm); });
1026cf69771bSopenharmony_ci}
1027cf69771bSopenharmony_ci
1028cf69771bSopenharmony_cibool TimerManager::CheckAllowWhileIdle(const std::shared_ptr<TimerInfo> &alarm)
1029cf69771bSopenharmony_ci{
1030cf69771bSopenharmony_ci#ifdef DEVICE_STANDBY_ENABLE
1031cf69771bSopenharmony_ci    if (TimePermission::CheckSystemUidCallingPermission(IPCSkeleton::GetCallingFullTokenID())) {
1032cf69771bSopenharmony_ci        std::vector<DevStandbyMgr::AllowInfo> restrictList;
1033cf69771bSopenharmony_ci        DevStandbyMgr::StandbyServiceClient::GetInstance().GetRestrictList(DevStandbyMgr::AllowType::TIMER,
1034cf69771bSopenharmony_ci            restrictList, REASON_APP_API);
1035cf69771bSopenharmony_ci        auto it = std::find_if(restrictList.begin(), restrictList.end(),
1036cf69771bSopenharmony_ci            [&alarm](const DevStandbyMgr::AllowInfo &allowInfo) { return allowInfo.GetName() == alarm->bundleName; });
1037cf69771bSopenharmony_ci        if (it != restrictList.end()) {
1038cf69771bSopenharmony_ci            return false;
1039cf69771bSopenharmony_ci        }
1040cf69771bSopenharmony_ci    }
1041cf69771bSopenharmony_ci
1042cf69771bSopenharmony_ci    if (TimePermission::CheckProxyCallingPermission()) {
1043cf69771bSopenharmony_ci        pid_t pid = IPCSkeleton::GetCallingPid();
1044cf69771bSopenharmony_ci        std::string procName = TimeFileUtils::GetNameByPid(pid);
1045cf69771bSopenharmony_ci        if (alarm->flags & static_cast<uint32_t>(INEXACT_REMINDER)) {
1046cf69771bSopenharmony_ci            return false;
1047cf69771bSopenharmony_ci        }
1048cf69771bSopenharmony_ci        std::vector<DevStandbyMgr::AllowInfo> restrictList;
1049cf69771bSopenharmony_ci        DevStandbyMgr::StandbyServiceClient::GetInstance().GetRestrictList(DevStandbyMgr::AllowType::TIMER,
1050cf69771bSopenharmony_ci            restrictList, REASON_NATIVE_API);
1051cf69771bSopenharmony_ci        auto it = std::find_if(restrictList.begin(), restrictList.end(),
1052cf69771bSopenharmony_ci            [procName](const DevStandbyMgr::AllowInfo &allowInfo) { return allowInfo.GetName() == procName; });
1053cf69771bSopenharmony_ci        if (it != restrictList.end()) {
1054cf69771bSopenharmony_ci            return false;
1055cf69771bSopenharmony_ci        }
1056cf69771bSopenharmony_ci    }
1057cf69771bSopenharmony_ci#endif
1058cf69771bSopenharmony_ci    return true;
1059cf69771bSopenharmony_ci}
1060cf69771bSopenharmony_ci
1061cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
1062cf69771bSopenharmony_cibool TimerManager::AdjustDeliveryTimeBasedOnDeviceIdle(const std::shared_ptr<TimerInfo> &alarm)
1063cf69771bSopenharmony_ci{
1064cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "start adjust timer, uid=%{public}d, id=%{public}" PRId64 "",
1065cf69771bSopenharmony_ci        alarm->uid, alarm->id);
1066cf69771bSopenharmony_ci    if (mPendingIdleUntil_ == alarm) {
1067cf69771bSopenharmony_ci        return false;
1068cf69771bSopenharmony_ci    }
1069cf69771bSopenharmony_ci    if (mPendingIdleUntil_ == nullptr) {
1070cf69771bSopenharmony_ci        auto itMap = delayedTimers_.find(alarm->id);
1071cf69771bSopenharmony_ci        if (itMap != delayedTimers_.end()) {
1072cf69771bSopenharmony_ci            std::chrono::milliseconds currentTime;
1073cf69771bSopenharmony_ci            if (alarm->type == RTC || alarm->type == RTC_WAKEUP) {
1074cf69771bSopenharmony_ci                currentTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
1075cf69771bSopenharmony_ci            } else {
1076cf69771bSopenharmony_ci                currentTime = duration_cast<milliseconds>(GetBootTimeNs().time_since_epoch());
1077cf69771bSopenharmony_ci            }
1078cf69771bSopenharmony_ci
1079cf69771bSopenharmony_ci            if (alarm->origWhen > currentTime) {
1080cf69771bSopenharmony_ci                auto offset = alarm->origWhen - currentTime;
1081cf69771bSopenharmony_ci                return alarm->UpdateWhenElapsedFromNow(GetBootTimeNs(), offset);
1082cf69771bSopenharmony_ci            }
1083cf69771bSopenharmony_ci            // 2 means the time of performing task.
1084cf69771bSopenharmony_ci            return alarm->UpdateWhenElapsedFromNow(GetBootTimeNs(), milliseconds(2));
1085cf69771bSopenharmony_ci        }
1086cf69771bSopenharmony_ci        return false;
1087cf69771bSopenharmony_ci    }
1088cf69771bSopenharmony_ci
1089cf69771bSopenharmony_ci    if (CheckAllowWhileIdle(alarm)) {
1090cf69771bSopenharmony_ci        TIME_HILOGD(TIME_MODULE_SERVICE, "Timer unrestricted, not adjust. id=%{public}" PRId64 "", alarm->id);
1091cf69771bSopenharmony_ci        return false;
1092cf69771bSopenharmony_ci    } else if (alarm->whenElapsed > mPendingIdleUntil_->whenElapsed) {
1093cf69771bSopenharmony_ci        TIME_HILOGD(TIME_MODULE_SERVICE, "Timer not allowed, not adjust. id=%{public}" PRId64 "", alarm->id);
1094cf69771bSopenharmony_ci        return false;
1095cf69771bSopenharmony_ci    } else {
1096cf69771bSopenharmony_ci        TIME_HILOGD(TIME_MODULE_SERVICE, "Timer not allowed, id=%{public}" PRId64 "", alarm->id);
1097cf69771bSopenharmony_ci        delayedTimers_[alarm->id] = alarm->whenElapsed;
1098cf69771bSopenharmony_ci        auto offset = ConvertToElapsed(mPendingIdleUntil_->when, mPendingIdleUntil_->type) - GetBootTimeNs();
1099cf69771bSopenharmony_ci        return alarm->UpdateWhenElapsedFromNow(GetBootTimeNs(), offset);
1100cf69771bSopenharmony_ci    }
1101cf69771bSopenharmony_ci}
1102cf69771bSopenharmony_ci
1103cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
1104cf69771bSopenharmony_cibool TimerManager::AdjustTimersBasedOnDeviceIdle()
1105cf69771bSopenharmony_ci{
1106cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "start adjust alarmBatches_.size=%{public}d",
1107cf69771bSopenharmony_ci        static_cast<int>(alarmBatches_.size()));
1108cf69771bSopenharmony_ci    bool isAdjust = false;
1109cf69771bSopenharmony_ci    for (const auto &batch : alarmBatches_) {
1110cf69771bSopenharmony_ci        auto n = batch->Size();
1111cf69771bSopenharmony_ci        for (unsigned int i = 0; i < n; i++) {
1112cf69771bSopenharmony_ci            auto alarm = batch->Get(i);
1113cf69771bSopenharmony_ci            isAdjust = AdjustDeliveryTimeBasedOnDeviceIdle(alarm) || isAdjust;
1114cf69771bSopenharmony_ci        }
1115cf69771bSopenharmony_ci    }
1116cf69771bSopenharmony_ci    return isAdjust;
1117cf69771bSopenharmony_ci}
1118cf69771bSopenharmony_ci
1119cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
1120cf69771bSopenharmony_cibool AddBatchLocked(std::vector<std::shared_ptr<Batch>> &list, const std::shared_ptr<Batch> &newBatch)
1121cf69771bSopenharmony_ci{
1122cf69771bSopenharmony_ci    auto it = std::upper_bound(list.begin(),
1123cf69771bSopenharmony_ci                               list.end(),
1124cf69771bSopenharmony_ci                               newBatch,
1125cf69771bSopenharmony_ci                               [](const std::shared_ptr<Batch> &first, const std::shared_ptr<Batch> &second) {
1126cf69771bSopenharmony_ci                                   return first->GetStart() < second->GetStart();
1127cf69771bSopenharmony_ci                               });
1128cf69771bSopenharmony_ci    list.insert(it, newBatch);
1129cf69771bSopenharmony_ci    return it == list.begin();
1130cf69771bSopenharmony_ci}
1131cf69771bSopenharmony_ci
1132cf69771bSopenharmony_cisteady_clock::time_point MaxTriggerTime(steady_clock::time_point now,
1133cf69771bSopenharmony_ci                                        steady_clock::time_point triggerAtTime,
1134cf69771bSopenharmony_ci                                        milliseconds interval)
1135cf69771bSopenharmony_ci{
1136cf69771bSopenharmony_ci    milliseconds futurity = (interval == milliseconds::zero()) ?
1137cf69771bSopenharmony_ci                            (duration_cast<milliseconds>(triggerAtTime - now)) : interval;
1138cf69771bSopenharmony_ci    if (futurity < MIN_FUZZABLE_INTERVAL) {
1139cf69771bSopenharmony_ci        futurity = milliseconds::zero();
1140cf69771bSopenharmony_ci    }
1141cf69771bSopenharmony_ci    return triggerAtTime + milliseconds(static_cast<long>(BATCH_WINDOW_COE * futurity.count()));
1142cf69771bSopenharmony_ci}
1143cf69771bSopenharmony_ci
1144cf69771bSopenharmony_cibool TimerManager::ShowTimerEntryMap(int fd)
1145cf69771bSopenharmony_ci{
1146cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
1147cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(entryMapMutex_);
1148cf69771bSopenharmony_ci    auto iter = timerEntryMap_.begin();
1149cf69771bSopenharmony_ci    for (; iter != timerEntryMap_.end(); iter++) {
1150cf69771bSopenharmony_ci        dprintf(fd, " - dump timer number   = %lu\n", iter->first);
1151cf69771bSopenharmony_ci        dprintf(fd, " * timer id            = %lu\n", iter->second->id);
1152cf69771bSopenharmony_ci        dprintf(fd, " * timer type          = %d\n", iter->second->type);
1153cf69771bSopenharmony_ci        dprintf(fd, " * timer flag          = %lu\n", iter->second->flag);
1154cf69771bSopenharmony_ci        dprintf(fd, " * timer window Length = %lld\n", iter->second->windowLength);
1155cf69771bSopenharmony_ci        dprintf(fd, " * timer interval      = %lu\n", iter->second->interval);
1156cf69771bSopenharmony_ci        dprintf(fd, " * timer uid           = %d\n\n", iter->second->uid);
1157cf69771bSopenharmony_ci    }
1158cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
1159cf69771bSopenharmony_ci    return true;
1160cf69771bSopenharmony_ci}
1161cf69771bSopenharmony_ci
1162cf69771bSopenharmony_cibool TimerManager::ShowTimerEntryById(int fd, uint64_t timerId)
1163cf69771bSopenharmony_ci{
1164cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
1165cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(entryMapMutex_);
1166cf69771bSopenharmony_ci    auto iter = timerEntryMap_.find(timerId);
1167cf69771bSopenharmony_ci    if (iter == timerEntryMap_.end()) {
1168cf69771bSopenharmony_ci        TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
1169cf69771bSopenharmony_ci        return false;
1170cf69771bSopenharmony_ci    } else {
1171cf69771bSopenharmony_ci        dprintf(fd, " - dump timer number   = %lu\n", iter->first);
1172cf69771bSopenharmony_ci        dprintf(fd, " * timer id            = %lu\n", iter->second->id);
1173cf69771bSopenharmony_ci        dprintf(fd, " * timer type          = %d\n", iter->second->type);
1174cf69771bSopenharmony_ci        dprintf(fd, " * timer window Length = %lld\n", iter->second->windowLength);
1175cf69771bSopenharmony_ci        dprintf(fd, " * timer interval      = %lu\n", iter->second->interval);
1176cf69771bSopenharmony_ci        dprintf(fd, " * timer uid           = %d\n\n", iter->second->uid);
1177cf69771bSopenharmony_ci    }
1178cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
1179cf69771bSopenharmony_ci    return true;
1180cf69771bSopenharmony_ci}
1181cf69771bSopenharmony_ci
1182cf69771bSopenharmony_cibool TimerManager::ShowTimerTriggerById(int fd, uint64_t timerId)
1183cf69771bSopenharmony_ci{
1184cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
1185cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
1186cf69771bSopenharmony_ci    for (size_t i = 0; i < alarmBatches_.size(); i++) {
1187cf69771bSopenharmony_ci        for (size_t j = 0; j < alarmBatches_[i]->Size(); j++) {
1188cf69771bSopenharmony_ci            if (alarmBatches_[i]->Get(j)->id == timerId) {
1189cf69771bSopenharmony_ci                dprintf(fd, " - dump timer id   = %lu\n", alarmBatches_[i]->Get(j)->id);
1190cf69771bSopenharmony_ci                dprintf(fd, " * timer trigger   = %lld\n", alarmBatches_[i]->Get(j)->origWhen);
1191cf69771bSopenharmony_ci            }
1192cf69771bSopenharmony_ci        }
1193cf69771bSopenharmony_ci    }
1194cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
1195cf69771bSopenharmony_ci    return true;
1196cf69771bSopenharmony_ci}
1197cf69771bSopenharmony_ci
1198cf69771bSopenharmony_cibool TimerManager::ShowIdleTimerInfo(int fd)
1199cf69771bSopenharmony_ci{
1200cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "start.");
1201cf69771bSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
1202cf69771bSopenharmony_ci    dprintf(fd, " - dump idle state         = %d\n", (mPendingIdleUntil_ != nullptr));
1203cf69771bSopenharmony_ci    if (mPendingIdleUntil_ != nullptr) {
1204cf69771bSopenharmony_ci        dprintf(fd, " - dump idle timer id  = %lu\n", mPendingIdleUntil_->id);
1205cf69771bSopenharmony_ci        dprintf(fd, " * timer type          = %d\n", mPendingIdleUntil_->type);
1206cf69771bSopenharmony_ci        dprintf(fd, " * timer flag          = %lu\n", mPendingIdleUntil_->flags);
1207cf69771bSopenharmony_ci        dprintf(fd, " * timer window Length = %lu\n", mPendingIdleUntil_->windowLength);
1208cf69771bSopenharmony_ci        dprintf(fd, " * timer interval      = %lu\n", mPendingIdleUntil_->repeatInterval);
1209cf69771bSopenharmony_ci        dprintf(fd, " * timer whenElapsed   = %lu\n", mPendingIdleUntil_->whenElapsed);
1210cf69771bSopenharmony_ci        dprintf(fd, " * timer uid           = %d\n\n", mPendingIdleUntil_->uid);
1211cf69771bSopenharmony_ci    }
1212cf69771bSopenharmony_ci    for (const auto &pendingTimer : pendingDelayTimers_) {
1213cf69771bSopenharmony_ci        dprintf(fd, " - dump pending delay timer id  = %lu\n", pendingTimer->id);
1214cf69771bSopenharmony_ci        dprintf(fd, " * timer type          = %d\n", pendingTimer->type);
1215cf69771bSopenharmony_ci        dprintf(fd, " * timer flag          = %lu\n", pendingTimer->flags);
1216cf69771bSopenharmony_ci        dprintf(fd, " * timer window Length = %lu\n", pendingTimer->windowLength);
1217cf69771bSopenharmony_ci        dprintf(fd, " * timer interval      = %lu\n", pendingTimer->repeatInterval);
1218cf69771bSopenharmony_ci        dprintf(fd, " * timer whenElapsed   = %lu\n", pendingTimer->whenElapsed);
1219cf69771bSopenharmony_ci        dprintf(fd, " * timer uid           = %d\n\n", pendingTimer->uid);
1220cf69771bSopenharmony_ci    }
1221cf69771bSopenharmony_ci    for (const auto &delayedTimer : delayedTimers_) {
1222cf69771bSopenharmony_ci        dprintf(fd, " - dump delayed timer id = %lu\n", delayedTimer.first);
1223cf69771bSopenharmony_ci        dprintf(fd, " * timer whenElapsed     = %lu\n", delayedTimer.second);
1224cf69771bSopenharmony_ci    }
1225cf69771bSopenharmony_ci    TIME_HILOGD(TIME_MODULE_SERVICE, "end.");
1226cf69771bSopenharmony_ci    return true;
1227cf69771bSopenharmony_ci}
1228cf69771bSopenharmony_ci
1229cf69771bSopenharmony_civoid TimerManager::OnUserRemoved(int userId)
1230cf69771bSopenharmony_ci{
1231cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_SERVICE, "Removed userId: %{public}d", userId);
1232cf69771bSopenharmony_ci    std::vector<std::shared_ptr<TimerEntry>> removeList;
1233cf69771bSopenharmony_ci    {
1234cf69771bSopenharmony_ci        std::lock_guard<std::mutex> lock(entryMapMutex_);
1235cf69771bSopenharmony_ci        for (auto it = timerEntryMap_.begin(); it != timerEntryMap_.end(); ++it) {
1236cf69771bSopenharmony_ci            int userIdOfTimer = -1;
1237cf69771bSopenharmony_ci            AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(it->second->uid, userIdOfTimer);
1238cf69771bSopenharmony_ci            if (userId == userIdOfTimer) {
1239cf69771bSopenharmony_ci                removeList.push_back(it->second);
1240cf69771bSopenharmony_ci            }
1241cf69771bSopenharmony_ci        }
1242cf69771bSopenharmony_ci    }
1243cf69771bSopenharmony_ci    for (auto it = removeList.begin(); it != removeList.end(); ++it) {
1244cf69771bSopenharmony_ci        DestroyTimer((*it)->id);
1245cf69771bSopenharmony_ci    }
1246cf69771bSopenharmony_ci}
1247cf69771bSopenharmony_ci
1248cf69771bSopenharmony_civoid TimerManager::HandleRSSDeath()
1249cf69771bSopenharmony_ci{
1250cf69771bSopenharmony_ci    TIME_HILOGI(TIME_MODULE_CLIENT, "RSSSaDeathRecipient died.");
1251cf69771bSopenharmony_ci    uint64_t id = 0;
1252cf69771bSopenharmony_ci    {
1253cf69771bSopenharmony_ci        std::lock_guard <std::mutex> lock(mutex_);
1254cf69771bSopenharmony_ci        if (mPendingIdleUntil_ != nullptr) {
1255cf69771bSopenharmony_ci            id = mPendingIdleUntil_->id;
1256cf69771bSopenharmony_ci        } else {
1257cf69771bSopenharmony_ci            return;
1258cf69771bSopenharmony_ci        }
1259cf69771bSopenharmony_ci    }
1260cf69771bSopenharmony_ci    StopTimerInner(id, true);
1261cf69771bSopenharmony_ci}
1262cf69771bSopenharmony_ci
1263cf69771bSopenharmony_civoid TimerManager::HandleRepeatTimer(
1264cf69771bSopenharmony_ci    const std::shared_ptr<TimerInfo> &timer, std::chrono::steady_clock::time_point nowElapsed)
1265cf69771bSopenharmony_ci{
1266cf69771bSopenharmony_ci    if (timer->repeatInterval > milliseconds::zero()) {
1267cf69771bSopenharmony_ci        uint64_t count = 1 + static_cast<uint64_t>(
1268cf69771bSopenharmony_ci            duration_cast<milliseconds>(nowElapsed - timer->whenElapsed) / timer->repeatInterval);
1269cf69771bSopenharmony_ci        auto delta = count * timer->repeatInterval;
1270cf69771bSopenharmony_ci        auto nextElapsed = timer->whenElapsed + delta;
1271cf69771bSopenharmony_ci        SetHandlerLocked(timer->id, timer->type, timer->when + delta, nextElapsed, timer->windowLength,
1272cf69771bSopenharmony_ci            MaxTriggerTime(nowElapsed, nextElapsed, timer->repeatInterval), timer->repeatInterval, timer->callback,
1273cf69771bSopenharmony_ci            timer->wantAgent, timer->flags, timer->uid, timer->pid, timer->bundleName);
1274cf69771bSopenharmony_ci    } else {
1275cf69771bSopenharmony_ci        TimerProxy::GetInstance().RemoveUidTimerMap(timer);
1276cf69771bSopenharmony_ci        TimerProxy::GetInstance().RemovePidTimerMap(timer);
1277cf69771bSopenharmony_ci    }
1278cf69771bSopenharmony_ci}
1279cf69771bSopenharmony_ci
1280cf69771bSopenharmony_ciinline bool TimerManager::CheckNeedRecoverOnReboot(std::string bundleName, int type)
1281cf69771bSopenharmony_ci{
1282cf69771bSopenharmony_ci    return (std::find(NEED_RECOVER_ON_REBOOT.begin(), NEED_RECOVER_ON_REBOOT.end(), bundleName) !=
1283cf69771bSopenharmony_ci        NEED_RECOVER_ON_REBOOT.end() && (type == RTC || type == RTC_WAKEUP));
1284cf69771bSopenharmony_ci}
1285cf69771bSopenharmony_ci
1286cf69771bSopenharmony_ci#ifdef POWER_MANAGER_ENABLE
1287cf69771bSopenharmony_ci// needs to acquire the lock `mutex_` before calling this method
1288cf69771bSopenharmony_civoid TimerManager::HandleRunningLock(const std::shared_ptr<Batch> &firstWakeup)
1289cf69771bSopenharmony_ci{
1290cf69771bSopenharmony_ci    auto currentTime = duration_cast<nanoseconds>(GetBootTimeNs().time_since_epoch()).count();
1291cf69771bSopenharmony_ci    auto nextTimerOffset =
1292cf69771bSopenharmony_ci        duration_cast<nanoseconds>(firstWakeup->GetStart().time_since_epoch()).count() - currentTime;
1293cf69771bSopenharmony_ci    auto lockOffset = currentTime - lockExpiredTime_;
1294cf69771bSopenharmony_ci    if (nextTimerOffset > 0 && nextTimerOffset <= USE_LOCK_TIME_IN_NANO &&
1295cf69771bSopenharmony_ci        ((lockOffset < 0 && std::abs(lockOffset) <= nextTimerOffset) || lockOffset >= 0)) {
1296cf69771bSopenharmony_ci        auto firstAlarm = firstWakeup->Get(0);
1297cf69771bSopenharmony_ci        if (firstAlarm == nullptr) {
1298cf69771bSopenharmony_ci            TIME_HILOGI(TIME_MODULE_SERVICE, "first alarm is null");
1299cf69771bSopenharmony_ci            return;
1300cf69771bSopenharmony_ci        }
1301cf69771bSopenharmony_ci        auto holdLockTime = nextTimerOffset + ONE_HUNDRED_MILLI;
1302cf69771bSopenharmony_ci        TIME_HILOGI(TIME_MODULE_SERVICE, "runningLock time:%{public}" PRIu64 ", timerId:%{public}"
1303cf69771bSopenharmony_ci                    PRIu64", uid:%{public}d  bundleName=%{public}s", static_cast<uint64_t>(holdLockTime),
1304cf69771bSopenharmony_ci                    firstAlarm->id, firstAlarm->uid, firstAlarm->bundleName.c_str());
1305cf69771bSopenharmony_ci        lockExpiredTime_ = currentTime + holdLockTime;
1306cf69771bSopenharmony_ci        AddRunningLock(holdLockTime);
1307cf69771bSopenharmony_ci    }
1308cf69771bSopenharmony_ci}
1309cf69771bSopenharmony_ci
1310cf69771bSopenharmony_civoid TimerManager::AddRunningLockRetry(long long holdLockTime)
1311cf69771bSopenharmony_ci{
1312cf69771bSopenharmony_ci    auto retryRegister = [this, holdLockTime]() {
1313cf69771bSopenharmony_ci        for (int i = 0; i < POWER_RETRY_TIMES; i++) {
1314cf69771bSopenharmony_ci            usleep(POWER_RETRY_INTERVAL);
1315cf69771bSopenharmony_ci            runningLock_->Lock(static_cast<int32_t>(holdLockTime / NANO_TO_MILLI));
1316cf69771bSopenharmony_ci            if (runningLock_->IsUsed()) {
1317cf69771bSopenharmony_ci                return;
1318cf69771bSopenharmony_ci            }
1319cf69771bSopenharmony_ci        }
1320cf69771bSopenharmony_ci    };
1321cf69771bSopenharmony_ci    std::thread thread(retryRegister);
1322cf69771bSopenharmony_ci    thread.detach();
1323cf69771bSopenharmony_ci}
1324cf69771bSopenharmony_ci
1325cf69771bSopenharmony_civoid TimerManager::AddRunningLock(long long holdLockTime)
1326cf69771bSopenharmony_ci{
1327cf69771bSopenharmony_ci    if (runningLock_ == nullptr) {
1328cf69771bSopenharmony_ci        std::lock_guard<std::mutex> lock(runningLockMutex_);
1329cf69771bSopenharmony_ci        if (runningLock_ == nullptr) {
1330cf69771bSopenharmony_ci            TIME_HILOGI(TIME_MODULE_SERVICE, "runningLock is nullptr, create runningLock");
1331cf69771bSopenharmony_ci            runningLock_ = PowerMgr::PowerMgrClient::GetInstance().CreateRunningLock("timeServiceRunningLock",
1332cf69771bSopenharmony_ci                PowerMgr::RunningLockType::RUNNINGLOCK_BACKGROUND_NOTIFICATION);
1333cf69771bSopenharmony_ci        }
1334cf69771bSopenharmony_ci    }
1335cf69771bSopenharmony_ci    if (runningLock_ != nullptr) {
1336cf69771bSopenharmony_ci        runningLock_->Lock(static_cast<int32_t>(holdLockTime / NANO_TO_MILLI));
1337cf69771bSopenharmony_ci        if (!runningLock_->IsUsed()) {
1338cf69771bSopenharmony_ci            AddRunningLockRetry(holdLockTime);
1339cf69771bSopenharmony_ci        }
1340cf69771bSopenharmony_ci    }
1341cf69771bSopenharmony_ci}
1342cf69771bSopenharmony_ci#endif
1343cf69771bSopenharmony_ci} // MiscServices
1344cf69771bSopenharmony_ci} // OHOS