/* * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "running_lock_impl.h" #include "hdf_base.h" #include "power_hdf_log.h" #include "system_operation.h" namespace OHOS { namespace HDI { namespace Power { namespace V1_2 { namespace { const std::string RUNNINGLOCK_TAG_BACKGROUND_INVALID = "OHOS.RunningLock.Background.Invalid"; const std::string RUNNINGLOCK_TAG_BACKGROUND_PHONE = "OHOS.RunningLock.Background.Phone"; const std::string RUNNINGLOCK_TAG_BACKGROUND_NOTIFICATION = "OHOS.RunningLock.Background.Notification"; const std::string RUNNINGLOCK_TAG_BACKGROUND_AUDIO = "OHOS.RunningLock.Background.Audio"; const std::string RUNNINGLOCK_TAG_BACKGROUND_SPORT = "OHOS.RunningLock.Background.Sport"; const std::string RUNNINGLOCK_TAG_BACKGROUND_NAVIGATION = "OHOS.RunningLock.Background.Navigation"; const std::string RUNNINGLOCK_TAG_BACKGROUND_TASK = "OHOS.RunningLock.Background.Task"; const std::string RUNNINGLOCK_TAG_BACKGROUND_PHONEEXT = "OHOS.RunningLock.Background.PhoneExt"; constexpr int32_t DEFAULT_TIMEOUT = 3000; } // namespace std::mutex RunningLockImpl::mutex_; int32_t RunningLockImpl::defaultTimeOutMs_ = DEFAULT_TIMEOUT; std::unique_ptr<RunningLockTimerHandler> RunningLockImpl::timerHandler_ = nullptr; std::map<RunningLockType, std::shared_ptr<RunningLockCounter>> RunningLockImpl::lockCounters_ = {}; sptr<IPowerRunningLockCallback> g_iPowerRunningLockCallback = nullptr; int32_t RunningLockImpl::Hold(const RunningLockInfo &info, PowerHdfState state, uint64_t lockid, const std::string &bundleName) { std::lock_guard<std::mutex> lock(mutex_); if (info.name.empty()) { HDF_LOGW("Runninglock hold failed, name is empty"); return HDF_ERR_INVALID_PARAM; } RunningLockInfo filledInfo = FillRunningLockInfo(info); if (!IsValidType(filledInfo.type, state)) { HDF_LOGW("Runninglock hold failed, type=%{public}d or state=%{public}d is invalid", filledInfo.type, state); return HDF_ERR_INVALID_PARAM; } auto iterator = lockCounters_.find(filledInfo.type); if (iterator == lockCounters_.end()) { auto pair = lockCounters_.emplace(filledInfo.type, std::make_shared<RunningLockCounter>(filledInfo.type, GetRunningLockTag(filledInfo.type))); if (pair.second == false) { HDF_LOGW("Runninglock hold failed, type=%{public}d is not in lockCounters", filledInfo.type); return HDF_FAILURE; } iterator = pair.first; } std::shared_ptr<RunningLockCounter> lockCounter = iterator->second; if (lockCounter->Increase(filledInfo) != HDF_SUCCESS) { return HDF_FAILURE; } if (filledInfo.timeoutMs > 0) { if (timerHandler_ == nullptr) { timerHandler_ = std::make_unique<RunningLockTimerHandler>(); } std::function<void()> unholdFunc = std::bind(&RunningLockImpl::Unhold, filledInfo, lockid, bundleName); timerHandler_->RegisterRunningLockTimer(filledInfo, unholdFunc); } RunningLockImpl::NotifyChanged(filledInfo, lockid, bundleName, "DUBAI_TAG_RUNNINGLOCK_ADD"); return HDF_SUCCESS; } int32_t RunningLockImpl::Unhold(const RunningLockInfo &info, uint64_t lockid, const std::string &bundleName) { std::lock_guard<std::mutex> lock(mutex_); if (info.name.empty()) { HDF_LOGW("Runninglock unhold failed, name is empty"); return HDF_ERR_INVALID_PARAM; } RunningLockInfo filledInfo = FillRunningLockInfo(info); if (!IsValidType(filledInfo.type)) { HDF_LOGW("Runninglock unhold failed, type=%{public}d is invalid", filledInfo.type); return HDF_ERR_INVALID_PARAM; } auto iterator = lockCounters_.find(filledInfo.type); if (iterator == lockCounters_.end()) { HDF_LOGW("type=%{public}d is not in lockCounters, no need to unhold", filledInfo.type); return HDF_ERR_NOT_SUPPORT; } if (timerHandler_ != nullptr) { timerHandler_->UnregisterRunningLockTimer(filledInfo); } std::shared_ptr<RunningLockCounter> lockCounter = iterator->second; int32_t status = lockCounter->Decrease(filledInfo); if (status == HDF_SUCCESS) { RunningLockImpl::NotifyChanged(filledInfo, lockid, bundleName, "DUBAI_TAG_RUNNINGLOCK_REMOVE"); } return status; } int32_t RunningLockImpl::HoldLock(const RunningLockInfo &info, PowerHdfState state, uint64_t lockid, const std::string &bundleName) { std::lock_guard<std::mutex> lock(mutex_); if (!IsValidType(info.type, state)) { HDF_LOGW("HoldLock failed, type=%{public}d or state=%{public}d is invalid", info.type, state); return HDF_ERR_INVALID_PARAM; } int32_t status = SystemOperation::WriteWakeLock(GetRunningLockTagInner(info.type)); return status; } int32_t RunningLockImpl::UnholdLock(const RunningLockInfo &info, uint64_t lockid, const std::string &bundleName) { std::lock_guard<std::mutex> lock(mutex_); if (!IsValidType(info.type)) { HDF_LOGW("UnholdLock failed, type=%{public}d is invalid", info.type); return HDF_ERR_INVALID_PARAM; } int32_t status = SystemOperation::WriteWakeUnlock(GetRunningLockTagInner(info.type)); return status; } void RunningLockImpl::Clean() { HDF_LOGI("start to clear running locks"); std::lock_guard<std::mutex> lock(mutex_); if (timerHandler_ != nullptr) { timerHandler_->Clean(); } for (auto &iter : lockCounters_) { HDF_LOGI("clear running lock type %{public}d", iter.first); SystemOperation::WriteWakeUnlock(GetRunningLockTag(iter.first)); iter.second->Clean(); } lockCounters_.clear(); } uint32_t RunningLockImpl::GetCount(RunningLockType type) { std::lock_guard<std::mutex> lock(mutex_); uint32_t count = 0; auto iterator = lockCounters_.find(type); if (iterator != lockCounters_.end()) { count = iterator->second->GetCount(); } return count; } void RunningLockImpl::SetDefaultTimeOutMs(int32_t timeOutMs) { std::lock_guard<std::mutex> lock(mutex_); if (timeOutMs > 0) { defaultTimeOutMs_ = timeOutMs; } } bool RunningLockImpl::IsValidType(RunningLockType type, PowerHdfState state) { switch (state) { case PowerHdfState::SLEEP: case PowerHdfState::INACTIVE: case PowerHdfState::AWAKE: return type == RUNNINGLOCK_BACKGROUND_PHONE || type == RUNNINGLOCK_BACKGROUND_NOTIFICATION || type == RUNNINGLOCK_BACKGROUND_AUDIO || type == RUNNINGLOCK_BACKGROUND_SPORT || type == RUNNINGLOCK_BACKGROUND_NAVIGATION || type == RUNNINGLOCK_BACKGROUND_TASK; default: break; } return false; } RunningLockInfo RunningLockImpl::FillRunningLockInfo(const RunningLockInfo &info) { struct RunningLockInfo filledInfo { .name = info.name, .type = info.type, .timeoutMs = info.timeoutMs, .pid = info.pid, .uid = info.uid, }; if (static_cast<uint32_t>(filledInfo.type) == 0) { filledInfo.type = RunningLockType::RUNNINGLOCK_BACKGROUND_TASK; } if (filledInfo.timeoutMs == 0) { filledInfo.timeoutMs = defaultTimeOutMs_; } return filledInfo; } std::string RunningLockImpl::GetRunningLockTag(RunningLockType type) { switch (type) { case RunningLockType::RUNNINGLOCK_BACKGROUND_PHONE: return RUNNINGLOCK_TAG_BACKGROUND_PHONEEXT; case RunningLockType::RUNNINGLOCK_BACKGROUND_NOTIFICATION: return RUNNINGLOCK_TAG_BACKGROUND_NOTIFICATION; case RunningLockType::RUNNINGLOCK_BACKGROUND_AUDIO: return RUNNINGLOCK_TAG_BACKGROUND_AUDIO; case RunningLockType::RUNNINGLOCK_BACKGROUND_SPORT: return RUNNINGLOCK_TAG_BACKGROUND_SPORT; case RunningLockType::RUNNINGLOCK_BACKGROUND_NAVIGATION: return RUNNINGLOCK_TAG_BACKGROUND_NAVIGATION; case RunningLockType::RUNNINGLOCK_BACKGROUND_TASK: return RUNNINGLOCK_TAG_BACKGROUND_TASK; default: { HDF_LOGE("type=%{public}d is invalid, there is no corresponding tag", type); return RUNNINGLOCK_TAG_BACKGROUND_INVALID; } } } std::string RunningLockImpl::GetRunningLockTagInner(RunningLockType type) { switch (type) { case RunningLockType::RUNNINGLOCK_BACKGROUND_PHONE: return RUNNINGLOCK_TAG_BACKGROUND_PHONE; case RunningLockType::RUNNINGLOCK_BACKGROUND_NOTIFICATION: return RUNNINGLOCK_TAG_BACKGROUND_NOTIFICATION; case RunningLockType::RUNNINGLOCK_BACKGROUND_AUDIO: return RUNNINGLOCK_TAG_BACKGROUND_AUDIO; case RunningLockType::RUNNINGLOCK_BACKGROUND_SPORT: return RUNNINGLOCK_TAG_BACKGROUND_SPORT; case RunningLockType::RUNNINGLOCK_BACKGROUND_NAVIGATION: return RUNNINGLOCK_TAG_BACKGROUND_NAVIGATION; case RunningLockType::RUNNINGLOCK_BACKGROUND_TASK: return RUNNINGLOCK_TAG_BACKGROUND_TASK; default: { HDF_LOGE("type=%{public}d is invalid, there is no corresponding tag", type); return RUNNINGLOCK_TAG_BACKGROUND_INVALID; } } } void RunningLockImpl::RegisterRunningLockCallback(const sptr<IPowerRunningLockCallback> &iPowerRunningLockCallback) { std::lock_guard<std::mutex> lock(mutex_); g_iPowerRunningLockCallback = iPowerRunningLockCallback; HDF_LOGI("RegisterRunningLockCallback success"); } void RunningLockImpl::UnRegisterRunningLockCallback() { std::lock_guard<std::mutex> lock(mutex_); g_iPowerRunningLockCallback = nullptr; HDF_LOGI("UnRegisterRunningLockCallback success"); } void RunningLockImpl::NotifyChanged(const RunningLockInfo &info, const uint64_t &lockid, const std::string &bundleName, const std::string &tag) { int32_t pid = info.pid; int32_t uid = info.uid; int32_t type = static_cast<int32_t>(info.type); std::string name = info.name; auto now = std::chrono::system_clock::now(); auto timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count(); std::string message; message.append("LOCKID=").append(std::to_string(lockid)) .append(" PID=").append(std::to_string(pid)) .append(" UID=").append(std::to_string(uid)) .append(" TYPE=").append(std::to_string(type)) .append(" NAME=").append(name) .append(" BUNDLENAME=").append(bundleName) .append(" TAG=").append(tag) .append(" TIMESTAMP=").append(std::to_string(timestamp)); HDF_LOGI("runninglock message: %{public}s, timeout: %{public}d", message.c_str(), info.timeoutMs); if (g_iPowerRunningLockCallback != nullptr) { g_iPowerRunningLockCallback->HandleRunningLockMessage(message); } } } // namespace V1_2 } // namespace Power } // namespace HDI } // namespace OHOS