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 ¶s) 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 ¶s, 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