1094332d3Sopenharmony_ci/* 2094332d3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License. 5094332d3Sopenharmony_ci * You may obtain a copy of the License at 6094332d3Sopenharmony_ci * 7094332d3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8094332d3Sopenharmony_ci * 9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and 13094332d3Sopenharmony_ci * limitations under the License. 14094332d3Sopenharmony_ci */ 15094332d3Sopenharmony_ci 16094332d3Sopenharmony_ci#include "running_lock_impl.h" 17094332d3Sopenharmony_ci 18094332d3Sopenharmony_ci#include "hdf_base.h" 19094332d3Sopenharmony_ci#include "power_hdf_log.h" 20094332d3Sopenharmony_ci#include "system_operation.h" 21094332d3Sopenharmony_ci 22094332d3Sopenharmony_cinamespace OHOS { 23094332d3Sopenharmony_cinamespace HDI { 24094332d3Sopenharmony_cinamespace Power { 25094332d3Sopenharmony_cinamespace V1_2 { 26094332d3Sopenharmony_cinamespace { 27094332d3Sopenharmony_ciconst std::string RUNNINGLOCK_TAG_BACKGROUND_INVALID = "OHOS.RunningLock.Background.Invalid"; 28094332d3Sopenharmony_ciconst std::string RUNNINGLOCK_TAG_BACKGROUND_PHONE = "OHOS.RunningLock.Background.Phone"; 29094332d3Sopenharmony_ciconst std::string RUNNINGLOCK_TAG_BACKGROUND_NOTIFICATION = "OHOS.RunningLock.Background.Notification"; 30094332d3Sopenharmony_ciconst std::string RUNNINGLOCK_TAG_BACKGROUND_AUDIO = "OHOS.RunningLock.Background.Audio"; 31094332d3Sopenharmony_ciconst std::string RUNNINGLOCK_TAG_BACKGROUND_SPORT = "OHOS.RunningLock.Background.Sport"; 32094332d3Sopenharmony_ciconst std::string RUNNINGLOCK_TAG_BACKGROUND_NAVIGATION = "OHOS.RunningLock.Background.Navigation"; 33094332d3Sopenharmony_ciconst std::string RUNNINGLOCK_TAG_BACKGROUND_TASK = "OHOS.RunningLock.Background.Task"; 34094332d3Sopenharmony_ciconst std::string RUNNINGLOCK_TAG_BACKGROUND_PHONEEXT = "OHOS.RunningLock.Background.PhoneExt"; 35094332d3Sopenharmony_ciconstexpr int32_t DEFAULT_TIMEOUT = 3000; 36094332d3Sopenharmony_ci} // namespace 37094332d3Sopenharmony_cistd::mutex RunningLockImpl::mutex_; 38094332d3Sopenharmony_ciint32_t RunningLockImpl::defaultTimeOutMs_ = DEFAULT_TIMEOUT; 39094332d3Sopenharmony_cistd::unique_ptr<RunningLockTimerHandler> RunningLockImpl::timerHandler_ = nullptr; 40094332d3Sopenharmony_cistd::map<RunningLockType, std::shared_ptr<RunningLockCounter>> RunningLockImpl::lockCounters_ = {}; 41094332d3Sopenharmony_cisptr<IPowerRunningLockCallback> g_iPowerRunningLockCallback = nullptr; 42094332d3Sopenharmony_ci 43094332d3Sopenharmony_ciint32_t RunningLockImpl::Hold(const RunningLockInfo &info, PowerHdfState state, 44094332d3Sopenharmony_ci uint64_t lockid, const std::string &bundleName) 45094332d3Sopenharmony_ci{ 46094332d3Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 47094332d3Sopenharmony_ci if (info.name.empty()) { 48094332d3Sopenharmony_ci HDF_LOGW("Runninglock hold failed, name is empty"); 49094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 50094332d3Sopenharmony_ci } 51094332d3Sopenharmony_ci RunningLockInfo filledInfo = FillRunningLockInfo(info); 52094332d3Sopenharmony_ci if (!IsValidType(filledInfo.type, state)) { 53094332d3Sopenharmony_ci HDF_LOGW("Runninglock hold failed, type=%{public}d or state=%{public}d is invalid", filledInfo.type, state); 54094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 55094332d3Sopenharmony_ci } 56094332d3Sopenharmony_ci auto iterator = lockCounters_.find(filledInfo.type); 57094332d3Sopenharmony_ci if (iterator == lockCounters_.end()) { 58094332d3Sopenharmony_ci auto pair = lockCounters_.emplace(filledInfo.type, 59094332d3Sopenharmony_ci std::make_shared<RunningLockCounter>(filledInfo.type, GetRunningLockTag(filledInfo.type))); 60094332d3Sopenharmony_ci if (pair.second == false) { 61094332d3Sopenharmony_ci HDF_LOGW("Runninglock hold failed, type=%{public}d is not in lockCounters", filledInfo.type); 62094332d3Sopenharmony_ci return HDF_FAILURE; 63094332d3Sopenharmony_ci } 64094332d3Sopenharmony_ci iterator = pair.first; 65094332d3Sopenharmony_ci } 66094332d3Sopenharmony_ci std::shared_ptr<RunningLockCounter> lockCounter = iterator->second; 67094332d3Sopenharmony_ci if (lockCounter->Increase(filledInfo) != HDF_SUCCESS) { 68094332d3Sopenharmony_ci return HDF_FAILURE; 69094332d3Sopenharmony_ci } 70094332d3Sopenharmony_ci if (filledInfo.timeoutMs > 0) { 71094332d3Sopenharmony_ci if (timerHandler_ == nullptr) { 72094332d3Sopenharmony_ci timerHandler_ = std::make_unique<RunningLockTimerHandler>(); 73094332d3Sopenharmony_ci } 74094332d3Sopenharmony_ci std::function<void()> unholdFunc = std::bind(&RunningLockImpl::Unhold, filledInfo, lockid, bundleName); 75094332d3Sopenharmony_ci timerHandler_->RegisterRunningLockTimer(filledInfo, unholdFunc); 76094332d3Sopenharmony_ci } 77094332d3Sopenharmony_ci RunningLockImpl::NotifyChanged(filledInfo, lockid, bundleName, "DUBAI_TAG_RUNNINGLOCK_ADD"); 78094332d3Sopenharmony_ci return HDF_SUCCESS; 79094332d3Sopenharmony_ci} 80094332d3Sopenharmony_ci 81094332d3Sopenharmony_ciint32_t RunningLockImpl::Unhold(const RunningLockInfo &info, 82094332d3Sopenharmony_ci uint64_t lockid, const std::string &bundleName) 83094332d3Sopenharmony_ci{ 84094332d3Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 85094332d3Sopenharmony_ci if (info.name.empty()) { 86094332d3Sopenharmony_ci HDF_LOGW("Runninglock unhold failed, name is empty"); 87094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 88094332d3Sopenharmony_ci } 89094332d3Sopenharmony_ci RunningLockInfo filledInfo = FillRunningLockInfo(info); 90094332d3Sopenharmony_ci if (!IsValidType(filledInfo.type)) { 91094332d3Sopenharmony_ci HDF_LOGW("Runninglock unhold failed, type=%{public}d is invalid", filledInfo.type); 92094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 93094332d3Sopenharmony_ci } 94094332d3Sopenharmony_ci auto iterator = lockCounters_.find(filledInfo.type); 95094332d3Sopenharmony_ci if (iterator == lockCounters_.end()) { 96094332d3Sopenharmony_ci HDF_LOGW("type=%{public}d is not in lockCounters, no need to unhold", filledInfo.type); 97094332d3Sopenharmony_ci return HDF_ERR_NOT_SUPPORT; 98094332d3Sopenharmony_ci } 99094332d3Sopenharmony_ci if (timerHandler_ != nullptr) { 100094332d3Sopenharmony_ci timerHandler_->UnregisterRunningLockTimer(filledInfo); 101094332d3Sopenharmony_ci } 102094332d3Sopenharmony_ci std::shared_ptr<RunningLockCounter> lockCounter = iterator->second; 103094332d3Sopenharmony_ci int32_t status = lockCounter->Decrease(filledInfo); 104094332d3Sopenharmony_ci if (status == HDF_SUCCESS) { 105094332d3Sopenharmony_ci RunningLockImpl::NotifyChanged(filledInfo, lockid, bundleName, "DUBAI_TAG_RUNNINGLOCK_REMOVE"); 106094332d3Sopenharmony_ci } 107094332d3Sopenharmony_ci return status; 108094332d3Sopenharmony_ci} 109094332d3Sopenharmony_ci 110094332d3Sopenharmony_ciint32_t RunningLockImpl::HoldLock(const RunningLockInfo &info, PowerHdfState state, 111094332d3Sopenharmony_ci uint64_t lockid, const std::string &bundleName) 112094332d3Sopenharmony_ci{ 113094332d3Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 114094332d3Sopenharmony_ci if (!IsValidType(info.type, state)) { 115094332d3Sopenharmony_ci HDF_LOGW("HoldLock failed, type=%{public}d or state=%{public}d is invalid", info.type, state); 116094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 117094332d3Sopenharmony_ci } 118094332d3Sopenharmony_ci int32_t status = SystemOperation::WriteWakeLock(GetRunningLockTagInner(info.type)); 119094332d3Sopenharmony_ci return status; 120094332d3Sopenharmony_ci} 121094332d3Sopenharmony_ci 122094332d3Sopenharmony_ciint32_t RunningLockImpl::UnholdLock(const RunningLockInfo &info, 123094332d3Sopenharmony_ci uint64_t lockid, const std::string &bundleName) 124094332d3Sopenharmony_ci{ 125094332d3Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 126094332d3Sopenharmony_ci if (!IsValidType(info.type)) { 127094332d3Sopenharmony_ci HDF_LOGW("UnholdLock failed, type=%{public}d is invalid", info.type); 128094332d3Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 129094332d3Sopenharmony_ci } 130094332d3Sopenharmony_ci int32_t status = SystemOperation::WriteWakeUnlock(GetRunningLockTagInner(info.type)); 131094332d3Sopenharmony_ci return status; 132094332d3Sopenharmony_ci} 133094332d3Sopenharmony_ci 134094332d3Sopenharmony_civoid RunningLockImpl::Clean() 135094332d3Sopenharmony_ci{ 136094332d3Sopenharmony_ci HDF_LOGI("start to clear running locks"); 137094332d3Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 138094332d3Sopenharmony_ci if (timerHandler_ != nullptr) { 139094332d3Sopenharmony_ci timerHandler_->Clean(); 140094332d3Sopenharmony_ci } 141094332d3Sopenharmony_ci 142094332d3Sopenharmony_ci for (auto &iter : lockCounters_) { 143094332d3Sopenharmony_ci HDF_LOGI("clear running lock type %{public}d", iter.first); 144094332d3Sopenharmony_ci SystemOperation::WriteWakeUnlock(GetRunningLockTag(iter.first)); 145094332d3Sopenharmony_ci iter.second->Clean(); 146094332d3Sopenharmony_ci } 147094332d3Sopenharmony_ci lockCounters_.clear(); 148094332d3Sopenharmony_ci} 149094332d3Sopenharmony_ci 150094332d3Sopenharmony_ciuint32_t RunningLockImpl::GetCount(RunningLockType type) 151094332d3Sopenharmony_ci{ 152094332d3Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 153094332d3Sopenharmony_ci uint32_t count = 0; 154094332d3Sopenharmony_ci auto iterator = lockCounters_.find(type); 155094332d3Sopenharmony_ci if (iterator != lockCounters_.end()) { 156094332d3Sopenharmony_ci count = iterator->second->GetCount(); 157094332d3Sopenharmony_ci } 158094332d3Sopenharmony_ci return count; 159094332d3Sopenharmony_ci} 160094332d3Sopenharmony_ci 161094332d3Sopenharmony_civoid RunningLockImpl::SetDefaultTimeOutMs(int32_t timeOutMs) 162094332d3Sopenharmony_ci{ 163094332d3Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 164094332d3Sopenharmony_ci if (timeOutMs > 0) { 165094332d3Sopenharmony_ci defaultTimeOutMs_ = timeOutMs; 166094332d3Sopenharmony_ci } 167094332d3Sopenharmony_ci} 168094332d3Sopenharmony_ci 169094332d3Sopenharmony_cibool RunningLockImpl::IsValidType(RunningLockType type, PowerHdfState state) 170094332d3Sopenharmony_ci{ 171094332d3Sopenharmony_ci switch (state) { 172094332d3Sopenharmony_ci case PowerHdfState::SLEEP: 173094332d3Sopenharmony_ci case PowerHdfState::INACTIVE: 174094332d3Sopenharmony_ci case PowerHdfState::AWAKE: 175094332d3Sopenharmony_ci return type == RUNNINGLOCK_BACKGROUND_PHONE || type == RUNNINGLOCK_BACKGROUND_NOTIFICATION || 176094332d3Sopenharmony_ci type == RUNNINGLOCK_BACKGROUND_AUDIO || type == RUNNINGLOCK_BACKGROUND_SPORT || 177094332d3Sopenharmony_ci type == RUNNINGLOCK_BACKGROUND_NAVIGATION || type == RUNNINGLOCK_BACKGROUND_TASK; 178094332d3Sopenharmony_ci default: 179094332d3Sopenharmony_ci break; 180094332d3Sopenharmony_ci } 181094332d3Sopenharmony_ci return false; 182094332d3Sopenharmony_ci} 183094332d3Sopenharmony_ci 184094332d3Sopenharmony_ciRunningLockInfo RunningLockImpl::FillRunningLockInfo(const RunningLockInfo &info) 185094332d3Sopenharmony_ci{ 186094332d3Sopenharmony_ci struct RunningLockInfo filledInfo { 187094332d3Sopenharmony_ci .name = info.name, 188094332d3Sopenharmony_ci .type = info.type, 189094332d3Sopenharmony_ci .timeoutMs = info.timeoutMs, 190094332d3Sopenharmony_ci .pid = info.pid, 191094332d3Sopenharmony_ci .uid = info.uid, 192094332d3Sopenharmony_ci }; 193094332d3Sopenharmony_ci if (static_cast<uint32_t>(filledInfo.type) == 0) { 194094332d3Sopenharmony_ci filledInfo.type = RunningLockType::RUNNINGLOCK_BACKGROUND_TASK; 195094332d3Sopenharmony_ci } 196094332d3Sopenharmony_ci if (filledInfo.timeoutMs == 0) { 197094332d3Sopenharmony_ci filledInfo.timeoutMs = defaultTimeOutMs_; 198094332d3Sopenharmony_ci } 199094332d3Sopenharmony_ci return filledInfo; 200094332d3Sopenharmony_ci} 201094332d3Sopenharmony_ci 202094332d3Sopenharmony_cistd::string RunningLockImpl::GetRunningLockTag(RunningLockType type) 203094332d3Sopenharmony_ci{ 204094332d3Sopenharmony_ci switch (type) { 205094332d3Sopenharmony_ci case RunningLockType::RUNNINGLOCK_BACKGROUND_PHONE: 206094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_PHONEEXT; 207094332d3Sopenharmony_ci case RunningLockType::RUNNINGLOCK_BACKGROUND_NOTIFICATION: 208094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_NOTIFICATION; 209094332d3Sopenharmony_ci case RunningLockType::RUNNINGLOCK_BACKGROUND_AUDIO: 210094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_AUDIO; 211094332d3Sopenharmony_ci case RunningLockType::RUNNINGLOCK_BACKGROUND_SPORT: 212094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_SPORT; 213094332d3Sopenharmony_ci case RunningLockType::RUNNINGLOCK_BACKGROUND_NAVIGATION: 214094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_NAVIGATION; 215094332d3Sopenharmony_ci case RunningLockType::RUNNINGLOCK_BACKGROUND_TASK: 216094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_TASK; 217094332d3Sopenharmony_ci default: { 218094332d3Sopenharmony_ci HDF_LOGE("type=%{public}d is invalid, there is no corresponding tag", type); 219094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_INVALID; 220094332d3Sopenharmony_ci } 221094332d3Sopenharmony_ci } 222094332d3Sopenharmony_ci} 223094332d3Sopenharmony_ci 224094332d3Sopenharmony_cistd::string RunningLockImpl::GetRunningLockTagInner(RunningLockType type) 225094332d3Sopenharmony_ci{ 226094332d3Sopenharmony_ci switch (type) { 227094332d3Sopenharmony_ci case RunningLockType::RUNNINGLOCK_BACKGROUND_PHONE: 228094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_PHONE; 229094332d3Sopenharmony_ci case RunningLockType::RUNNINGLOCK_BACKGROUND_NOTIFICATION: 230094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_NOTIFICATION; 231094332d3Sopenharmony_ci case RunningLockType::RUNNINGLOCK_BACKGROUND_AUDIO: 232094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_AUDIO; 233094332d3Sopenharmony_ci case RunningLockType::RUNNINGLOCK_BACKGROUND_SPORT: 234094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_SPORT; 235094332d3Sopenharmony_ci case RunningLockType::RUNNINGLOCK_BACKGROUND_NAVIGATION: 236094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_NAVIGATION; 237094332d3Sopenharmony_ci case RunningLockType::RUNNINGLOCK_BACKGROUND_TASK: 238094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_TASK; 239094332d3Sopenharmony_ci default: { 240094332d3Sopenharmony_ci HDF_LOGE("type=%{public}d is invalid, there is no corresponding tag", type); 241094332d3Sopenharmony_ci return RUNNINGLOCK_TAG_BACKGROUND_INVALID; 242094332d3Sopenharmony_ci } 243094332d3Sopenharmony_ci } 244094332d3Sopenharmony_ci} 245094332d3Sopenharmony_ci 246094332d3Sopenharmony_civoid RunningLockImpl::RegisterRunningLockCallback(const sptr<IPowerRunningLockCallback> 247094332d3Sopenharmony_ci &iPowerRunningLockCallback) 248094332d3Sopenharmony_ci{ 249094332d3Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 250094332d3Sopenharmony_ci g_iPowerRunningLockCallback = iPowerRunningLockCallback; 251094332d3Sopenharmony_ci HDF_LOGI("RegisterRunningLockCallback success"); 252094332d3Sopenharmony_ci} 253094332d3Sopenharmony_ci 254094332d3Sopenharmony_civoid RunningLockImpl::UnRegisterRunningLockCallback() 255094332d3Sopenharmony_ci{ 256094332d3Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 257094332d3Sopenharmony_ci g_iPowerRunningLockCallback = nullptr; 258094332d3Sopenharmony_ci HDF_LOGI("UnRegisterRunningLockCallback success"); 259094332d3Sopenharmony_ci} 260094332d3Sopenharmony_ci 261094332d3Sopenharmony_civoid RunningLockImpl::NotifyChanged(const RunningLockInfo &info, 262094332d3Sopenharmony_ci const uint64_t &lockid, const std::string &bundleName, const std::string &tag) 263094332d3Sopenharmony_ci{ 264094332d3Sopenharmony_ci int32_t pid = info.pid; 265094332d3Sopenharmony_ci int32_t uid = info.uid; 266094332d3Sopenharmony_ci int32_t type = static_cast<int32_t>(info.type); 267094332d3Sopenharmony_ci std::string name = info.name; 268094332d3Sopenharmony_ci auto now = std::chrono::system_clock::now(); 269094332d3Sopenharmony_ci auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count(); 270094332d3Sopenharmony_ci std::string message; 271094332d3Sopenharmony_ci message.append("LOCKID=").append(std::to_string(lockid)) 272094332d3Sopenharmony_ci .append(" PID=").append(std::to_string(pid)) 273094332d3Sopenharmony_ci .append(" UID=").append(std::to_string(uid)) 274094332d3Sopenharmony_ci .append(" TYPE=").append(std::to_string(type)) 275094332d3Sopenharmony_ci .append(" NAME=").append(name) 276094332d3Sopenharmony_ci .append(" BUNDLENAME=").append(bundleName) 277094332d3Sopenharmony_ci .append(" TAG=").append(tag) 278094332d3Sopenharmony_ci .append(" TIMESTAMP=").append(std::to_string(timestamp)); 279094332d3Sopenharmony_ci HDF_LOGI("runninglock message: %{public}s, timeout: %{public}d", message.c_str(), info.timeoutMs); 280094332d3Sopenharmony_ci if (g_iPowerRunningLockCallback != nullptr) { 281094332d3Sopenharmony_ci g_iPowerRunningLockCallback->HandleRunningLockMessage(message); 282094332d3Sopenharmony_ci } 283094332d3Sopenharmony_ci} 284094332d3Sopenharmony_ci 285094332d3Sopenharmony_ci} // namespace V1_2 286094332d3Sopenharmony_ci} // namespace Power 287094332d3Sopenharmony_ci} // namespace HDI 288094332d3Sopenharmony_ci} // namespace OHOS 289