1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "running_lock_impl.h" 17 18#include "hdf_base.h" 19#include "power_hdf_log.h" 20#include "system_operation.h" 21 22namespace OHOS { 23namespace HDI { 24namespace Power { 25namespace V1_2 { 26namespace { 27const std::string RUNNINGLOCK_TAG_BACKGROUND_INVALID = "OHOS.RunningLock.Background.Invalid"; 28const std::string RUNNINGLOCK_TAG_BACKGROUND_PHONE = "OHOS.RunningLock.Background.Phone"; 29const std::string RUNNINGLOCK_TAG_BACKGROUND_NOTIFICATION = "OHOS.RunningLock.Background.Notification"; 30const std::string RUNNINGLOCK_TAG_BACKGROUND_AUDIO = "OHOS.RunningLock.Background.Audio"; 31const std::string RUNNINGLOCK_TAG_BACKGROUND_SPORT = "OHOS.RunningLock.Background.Sport"; 32const std::string RUNNINGLOCK_TAG_BACKGROUND_NAVIGATION = "OHOS.RunningLock.Background.Navigation"; 33const std::string RUNNINGLOCK_TAG_BACKGROUND_TASK = "OHOS.RunningLock.Background.Task"; 34const std::string RUNNINGLOCK_TAG_BACKGROUND_PHONEEXT = "OHOS.RunningLock.Background.PhoneExt"; 35constexpr int32_t DEFAULT_TIMEOUT = 3000; 36} // namespace 37std::mutex RunningLockImpl::mutex_; 38int32_t RunningLockImpl::defaultTimeOutMs_ = DEFAULT_TIMEOUT; 39std::unique_ptr<RunningLockTimerHandler> RunningLockImpl::timerHandler_ = nullptr; 40std::map<RunningLockType, std::shared_ptr<RunningLockCounter>> RunningLockImpl::lockCounters_ = {}; 41sptr<IPowerRunningLockCallback> g_iPowerRunningLockCallback = nullptr; 42 43int32_t RunningLockImpl::Hold(const RunningLockInfo &info, PowerHdfState state, 44 uint64_t lockid, const std::string &bundleName) 45{ 46 std::lock_guard<std::mutex> lock(mutex_); 47 if (info.name.empty()) { 48 HDF_LOGW("Runninglock hold failed, name is empty"); 49 return HDF_ERR_INVALID_PARAM; 50 } 51 RunningLockInfo filledInfo = FillRunningLockInfo(info); 52 if (!IsValidType(filledInfo.type, state)) { 53 HDF_LOGW("Runninglock hold failed, type=%{public}d or state=%{public}d is invalid", filledInfo.type, state); 54 return HDF_ERR_INVALID_PARAM; 55 } 56 auto iterator = lockCounters_.find(filledInfo.type); 57 if (iterator == lockCounters_.end()) { 58 auto pair = lockCounters_.emplace(filledInfo.type, 59 std::make_shared<RunningLockCounter>(filledInfo.type, GetRunningLockTag(filledInfo.type))); 60 if (pair.second == false) { 61 HDF_LOGW("Runninglock hold failed, type=%{public}d is not in lockCounters", filledInfo.type); 62 return HDF_FAILURE; 63 } 64 iterator = pair.first; 65 } 66 std::shared_ptr<RunningLockCounter> lockCounter = iterator->second; 67 if (lockCounter->Increase(filledInfo) != HDF_SUCCESS) { 68 return HDF_FAILURE; 69 } 70 if (filledInfo.timeoutMs > 0) { 71 if (timerHandler_ == nullptr) { 72 timerHandler_ = std::make_unique<RunningLockTimerHandler>(); 73 } 74 std::function<void()> unholdFunc = std::bind(&RunningLockImpl::Unhold, filledInfo, lockid, bundleName); 75 timerHandler_->RegisterRunningLockTimer(filledInfo, unholdFunc); 76 } 77 RunningLockImpl::NotifyChanged(filledInfo, lockid, bundleName, "DUBAI_TAG_RUNNINGLOCK_ADD"); 78 return HDF_SUCCESS; 79} 80 81int32_t RunningLockImpl::Unhold(const RunningLockInfo &info, 82 uint64_t lockid, const std::string &bundleName) 83{ 84 std::lock_guard<std::mutex> lock(mutex_); 85 if (info.name.empty()) { 86 HDF_LOGW("Runninglock unhold failed, name is empty"); 87 return HDF_ERR_INVALID_PARAM; 88 } 89 RunningLockInfo filledInfo = FillRunningLockInfo(info); 90 if (!IsValidType(filledInfo.type)) { 91 HDF_LOGW("Runninglock unhold failed, type=%{public}d is invalid", filledInfo.type); 92 return HDF_ERR_INVALID_PARAM; 93 } 94 auto iterator = lockCounters_.find(filledInfo.type); 95 if (iterator == lockCounters_.end()) { 96 HDF_LOGW("type=%{public}d is not in lockCounters, no need to unhold", filledInfo.type); 97 return HDF_ERR_NOT_SUPPORT; 98 } 99 if (timerHandler_ != nullptr) { 100 timerHandler_->UnregisterRunningLockTimer(filledInfo); 101 } 102 std::shared_ptr<RunningLockCounter> lockCounter = iterator->second; 103 int32_t status = lockCounter->Decrease(filledInfo); 104 if (status == HDF_SUCCESS) { 105 RunningLockImpl::NotifyChanged(filledInfo, lockid, bundleName, "DUBAI_TAG_RUNNINGLOCK_REMOVE"); 106 } 107 return status; 108} 109 110int32_t RunningLockImpl::HoldLock(const RunningLockInfo &info, PowerHdfState state, 111 uint64_t lockid, const std::string &bundleName) 112{ 113 std::lock_guard<std::mutex> lock(mutex_); 114 if (!IsValidType(info.type, state)) { 115 HDF_LOGW("HoldLock failed, type=%{public}d or state=%{public}d is invalid", info.type, state); 116 return HDF_ERR_INVALID_PARAM; 117 } 118 int32_t status = SystemOperation::WriteWakeLock(GetRunningLockTagInner(info.type)); 119 return status; 120} 121 122int32_t RunningLockImpl::UnholdLock(const RunningLockInfo &info, 123 uint64_t lockid, const std::string &bundleName) 124{ 125 std::lock_guard<std::mutex> lock(mutex_); 126 if (!IsValidType(info.type)) { 127 HDF_LOGW("UnholdLock failed, type=%{public}d is invalid", info.type); 128 return HDF_ERR_INVALID_PARAM; 129 } 130 int32_t status = SystemOperation::WriteWakeUnlock(GetRunningLockTagInner(info.type)); 131 return status; 132} 133 134void RunningLockImpl::Clean() 135{ 136 HDF_LOGI("start to clear running locks"); 137 std::lock_guard<std::mutex> lock(mutex_); 138 if (timerHandler_ != nullptr) { 139 timerHandler_->Clean(); 140 } 141 142 for (auto &iter : lockCounters_) { 143 HDF_LOGI("clear running lock type %{public}d", iter.first); 144 SystemOperation::WriteWakeUnlock(GetRunningLockTag(iter.first)); 145 iter.second->Clean(); 146 } 147 lockCounters_.clear(); 148} 149 150uint32_t RunningLockImpl::GetCount(RunningLockType type) 151{ 152 std::lock_guard<std::mutex> lock(mutex_); 153 uint32_t count = 0; 154 auto iterator = lockCounters_.find(type); 155 if (iterator != lockCounters_.end()) { 156 count = iterator->second->GetCount(); 157 } 158 return count; 159} 160 161void RunningLockImpl::SetDefaultTimeOutMs(int32_t timeOutMs) 162{ 163 std::lock_guard<std::mutex> lock(mutex_); 164 if (timeOutMs > 0) { 165 defaultTimeOutMs_ = timeOutMs; 166 } 167} 168 169bool RunningLockImpl::IsValidType(RunningLockType type, PowerHdfState state) 170{ 171 switch (state) { 172 case PowerHdfState::SLEEP: 173 case PowerHdfState::INACTIVE: 174 case PowerHdfState::AWAKE: 175 return type == RUNNINGLOCK_BACKGROUND_PHONE || type == RUNNINGLOCK_BACKGROUND_NOTIFICATION || 176 type == RUNNINGLOCK_BACKGROUND_AUDIO || type == RUNNINGLOCK_BACKGROUND_SPORT || 177 type == RUNNINGLOCK_BACKGROUND_NAVIGATION || type == RUNNINGLOCK_BACKGROUND_TASK; 178 default: 179 break; 180 } 181 return false; 182} 183 184RunningLockInfo RunningLockImpl::FillRunningLockInfo(const RunningLockInfo &info) 185{ 186 struct RunningLockInfo filledInfo { 187 .name = info.name, 188 .type = info.type, 189 .timeoutMs = info.timeoutMs, 190 .pid = info.pid, 191 .uid = info.uid, 192 }; 193 if (static_cast<uint32_t>(filledInfo.type) == 0) { 194 filledInfo.type = RunningLockType::RUNNINGLOCK_BACKGROUND_TASK; 195 } 196 if (filledInfo.timeoutMs == 0) { 197 filledInfo.timeoutMs = defaultTimeOutMs_; 198 } 199 return filledInfo; 200} 201 202std::string RunningLockImpl::GetRunningLockTag(RunningLockType type) 203{ 204 switch (type) { 205 case RunningLockType::RUNNINGLOCK_BACKGROUND_PHONE: 206 return RUNNINGLOCK_TAG_BACKGROUND_PHONEEXT; 207 case RunningLockType::RUNNINGLOCK_BACKGROUND_NOTIFICATION: 208 return RUNNINGLOCK_TAG_BACKGROUND_NOTIFICATION; 209 case RunningLockType::RUNNINGLOCK_BACKGROUND_AUDIO: 210 return RUNNINGLOCK_TAG_BACKGROUND_AUDIO; 211 case RunningLockType::RUNNINGLOCK_BACKGROUND_SPORT: 212 return RUNNINGLOCK_TAG_BACKGROUND_SPORT; 213 case RunningLockType::RUNNINGLOCK_BACKGROUND_NAVIGATION: 214 return RUNNINGLOCK_TAG_BACKGROUND_NAVIGATION; 215 case RunningLockType::RUNNINGLOCK_BACKGROUND_TASK: 216 return RUNNINGLOCK_TAG_BACKGROUND_TASK; 217 default: { 218 HDF_LOGE("type=%{public}d is invalid, there is no corresponding tag", type); 219 return RUNNINGLOCK_TAG_BACKGROUND_INVALID; 220 } 221 } 222} 223 224std::string RunningLockImpl::GetRunningLockTagInner(RunningLockType type) 225{ 226 switch (type) { 227 case RunningLockType::RUNNINGLOCK_BACKGROUND_PHONE: 228 return RUNNINGLOCK_TAG_BACKGROUND_PHONE; 229 case RunningLockType::RUNNINGLOCK_BACKGROUND_NOTIFICATION: 230 return RUNNINGLOCK_TAG_BACKGROUND_NOTIFICATION; 231 case RunningLockType::RUNNINGLOCK_BACKGROUND_AUDIO: 232 return RUNNINGLOCK_TAG_BACKGROUND_AUDIO; 233 case RunningLockType::RUNNINGLOCK_BACKGROUND_SPORT: 234 return RUNNINGLOCK_TAG_BACKGROUND_SPORT; 235 case RunningLockType::RUNNINGLOCK_BACKGROUND_NAVIGATION: 236 return RUNNINGLOCK_TAG_BACKGROUND_NAVIGATION; 237 case RunningLockType::RUNNINGLOCK_BACKGROUND_TASK: 238 return RUNNINGLOCK_TAG_BACKGROUND_TASK; 239 default: { 240 HDF_LOGE("type=%{public}d is invalid, there is no corresponding tag", type); 241 return RUNNINGLOCK_TAG_BACKGROUND_INVALID; 242 } 243 } 244} 245 246void RunningLockImpl::RegisterRunningLockCallback(const sptr<IPowerRunningLockCallback> 247 &iPowerRunningLockCallback) 248{ 249 std::lock_guard<std::mutex> lock(mutex_); 250 g_iPowerRunningLockCallback = iPowerRunningLockCallback; 251 HDF_LOGI("RegisterRunningLockCallback success"); 252} 253 254void RunningLockImpl::UnRegisterRunningLockCallback() 255{ 256 std::lock_guard<std::mutex> lock(mutex_); 257 g_iPowerRunningLockCallback = nullptr; 258 HDF_LOGI("UnRegisterRunningLockCallback success"); 259} 260 261void RunningLockImpl::NotifyChanged(const RunningLockInfo &info, 262 const uint64_t &lockid, const std::string &bundleName, const std::string &tag) 263{ 264 int32_t pid = info.pid; 265 int32_t uid = info.uid; 266 int32_t type = static_cast<int32_t>(info.type); 267 std::string name = info.name; 268 auto now = std::chrono::system_clock::now(); 269 auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count(); 270 std::string message; 271 message.append("LOCKID=").append(std::to_string(lockid)) 272 .append(" PID=").append(std::to_string(pid)) 273 .append(" UID=").append(std::to_string(uid)) 274 .append(" TYPE=").append(std::to_string(type)) 275 .append(" NAME=").append(name) 276 .append(" BUNDLENAME=").append(bundleName) 277 .append(" TAG=").append(tag) 278 .append(" TIMESTAMP=").append(std::to_string(timestamp)); 279 HDF_LOGI("runninglock message: %{public}s, timeout: %{public}d", message.c_str(), info.timeoutMs); 280 if (g_iPowerRunningLockCallback != nullptr) { 281 g_iPowerRunningLockCallback->HandleRunningLockMessage(message); 282 } 283} 284 285} // namespace V1_2 286} // namespace Power 287} // namespace HDI 288} // namespace OHOS 289