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
22 namespace OHOS {
23 namespace HDI {
24 namespace Power {
25 namespace V1_1 {
26 namespace {
27 const std::string RUNNINGLOCK_TAG_BACKGROUND_INVALID = "OHOS.RunningLock.Background.Invalid";
28 const std::string RUNNINGLOCK_TAG_BACKGROUND_PHONE = "OHOS.RunningLock.Background.Phone";
29 const std::string RUNNINGLOCK_TAG_BACKGROUND_NOTIFICATION = "OHOS.RunningLock.Background.Notification";
30 const std::string RUNNINGLOCK_TAG_BACKGROUND_AUDIO = "OHOS.RunningLock.Background.Audio";
31 const std::string RUNNINGLOCK_TAG_BACKGROUND_SPORT = "OHOS.RunningLock.Background.Sport";
32 const std::string RUNNINGLOCK_TAG_BACKGROUND_NAVIGATION = "OHOS.RunningLock.Background.Navigation";
33 const std::string RUNNINGLOCK_TAG_BACKGROUND_TASK = "OHOS.RunningLock.Background.Task";
34 constexpr int32_t DEFAULT_TIMEOUT = 3000;
35 } // namespace
36 std::mutex RunningLockImpl::mutex_;
37 int32_t RunningLockImpl::defaultTimeOutMs_ = DEFAULT_TIMEOUT;
38 std::unique_ptr<RunningLockTimerHandler> RunningLockImpl::timerHandler_ = nullptr;
39 std::map<RunningLockType, std::shared_ptr<RunningLockCounter>> RunningLockImpl::lockCounters_ = {};
40
Hold(const RunningLockInfo & info,PowerHdfState state)41 int32_t RunningLockImpl::Hold(const RunningLockInfo &info, PowerHdfState state)
42 {
43 std::lock_guard<std::mutex> lock(mutex_);
44 if (info.name.empty()) {
45 HDF_LOGW("Runninglock hold failed, name is empty");
46 return HDF_ERR_INVALID_PARAM;
47 }
48 RunningLockInfo filledInfo = FillRunningLockInfo(info);
49 if (!IsValidType(filledInfo.type, state)) {
50 HDF_LOGW("Runninglock hold failed, type=%{public}d or state=%{public}d is invalid", filledInfo.type, state);
51 return HDF_ERR_INVALID_PARAM;
52 }
53 auto iterator = lockCounters_.find(filledInfo.type);
54 if (iterator == lockCounters_.end()) {
55 auto pair = lockCounters_.emplace(filledInfo.type,
56 std::make_shared<RunningLockCounter>(filledInfo.type, GetRunningLockTag(filledInfo.type)));
57 if (pair.second == false) {
58 HDF_LOGW("Runninglock hold failed, type=%{public}d is not in lockCounters", filledInfo.type);
59 return HDF_FAILURE;
60 }
61 iterator = pair.first;
62 }
63 std::shared_ptr<RunningLockCounter> lockCounter = iterator->second;
64 if (lockCounter->Increase(filledInfo) != HDF_SUCCESS) {
65 return HDF_FAILURE;
66 }
67 if (filledInfo.timeoutMs > 0) {
68 if (timerHandler_ == nullptr) {
69 timerHandler_ = std::make_unique<RunningLockTimerHandler>();
70 }
71 std::function<void()> unholdFunc = std::bind(&RunningLockImpl::Unhold, filledInfo);
72 timerHandler_->RegisterRunningLockTimer(filledInfo, unholdFunc);
73 }
74 return HDF_SUCCESS;
75 }
76
Unhold(const RunningLockInfo & info)77 int32_t RunningLockImpl::Unhold(const RunningLockInfo &info)
78 {
79 std::lock_guard<std::mutex> lock(mutex_);
80 if (info.name.empty()) {
81 HDF_LOGW("Runninglock unhold failed, name is empty");
82 return HDF_ERR_INVALID_PARAM;
83 }
84 RunningLockInfo filledInfo = FillRunningLockInfo(info);
85 if (!IsValidType(filledInfo.type)) {
86 HDF_LOGW("Runninglock unhold failed, type=%{public}d is invalid", filledInfo.type);
87 return HDF_ERR_INVALID_PARAM;
88 }
89 auto iterator = lockCounters_.find(filledInfo.type);
90 if (iterator == lockCounters_.end()) {
91 HDF_LOGW("type=%{public}d is not in lockCounters, no need to unhold", filledInfo.type);
92 return HDF_ERR_NOT_SUPPORT;
93 }
94 if (timerHandler_ != nullptr) {
95 timerHandler_->UnregisterRunningLockTimer(filledInfo);
96 }
97 std::shared_ptr<RunningLockCounter> lockCounter = iterator->second;
98 int32_t status = lockCounter->Decrease(filledInfo);
99 return status;
100 }
101
Clean()102 void RunningLockImpl::Clean()
103 {
104 HDF_LOGI("start to clear running locks");
105 std::lock_guard<std::mutex> lock(mutex_);
106 if (timerHandler_ != nullptr) {
107 timerHandler_->Clean();
108 }
109
110 for (auto &iter : lockCounters_) {
111 HDF_LOGI("clear running lock type %{public}d", iter.first);
112 SystemOperation::WriteWakeUnlock(GetRunningLockTag(iter.first));
113 iter.second->Clean();
114 }
115 lockCounters_.clear();
116 }
117
GetCount(RunningLockType type)118 uint32_t RunningLockImpl::GetCount(RunningLockType type)
119 {
120 std::lock_guard<std::mutex> lock(mutex_);
121 int32_t count = 0;
122 auto iterator = lockCounters_.find(type);
123 if (iterator != lockCounters_.end()) {
124 count = iterator->second->GetCount();
125 }
126 return count;
127 }
128
SetDefaultTimeOutMs(int32_t timeOutMs)129 void RunningLockImpl::SetDefaultTimeOutMs(int32_t timeOutMs)
130 {
131 std::lock_guard<std::mutex> lock(mutex_);
132 if (timeOutMs > 0) {
133 defaultTimeOutMs_ = timeOutMs;
134 }
135 }
136
IsValidType(RunningLockType type,PowerHdfState state)137 bool RunningLockImpl::IsValidType(RunningLockType type, PowerHdfState state)
138 {
139 switch (state) {
140 case PowerHdfState::SLEEP:
141 return false;
142 case PowerHdfState::INACTIVE:
143 return type == RUNNINGLOCK_BACKGROUND_PHONE || type == RUNNINGLOCK_BACKGROUND_NOTIFICATION ||
144 type == RUNNINGLOCK_BACKGROUND_AUDIO;
145 case PowerHdfState::AWAKE:
146 return type == RUNNINGLOCK_BACKGROUND_PHONE || type == RUNNINGLOCK_BACKGROUND_NOTIFICATION ||
147 type == RUNNINGLOCK_BACKGROUND_AUDIO || type == RUNNINGLOCK_BACKGROUND_SPORT ||
148 type == RUNNINGLOCK_BACKGROUND_NAVIGATION || type == RUNNINGLOCK_BACKGROUND_TASK;
149 default:
150 break;
151 }
152 return false;
153 }
154
FillRunningLockInfo(const RunningLockInfo & info)155 RunningLockInfo RunningLockImpl::FillRunningLockInfo(const RunningLockInfo &info)
156 {
157 struct RunningLockInfo filledInfo {
158 .name = info.name,
159 .type = info.type,
160 .timeoutMs = info.timeoutMs,
161 .pid = info.pid,
162 .uid = info.uid,
163 };
164 if (static_cast<uint32_t>(filledInfo.type) == 0) {
165 filledInfo.type = RunningLockType::RUNNINGLOCK_BACKGROUND_TASK;
166 }
167 if (filledInfo.timeoutMs == 0) {
168 filledInfo.timeoutMs = defaultTimeOutMs_;
169 }
170 return filledInfo;
171 }
172
GetRunningLockTag(RunningLockType type)173 std::string RunningLockImpl::GetRunningLockTag(RunningLockType type)
174 {
175 switch (type) {
176 case RunningLockType::RUNNINGLOCK_BACKGROUND_PHONE:
177 return RUNNINGLOCK_TAG_BACKGROUND_PHONE;
178 case RunningLockType::RUNNINGLOCK_BACKGROUND_NOTIFICATION:
179 return RUNNINGLOCK_TAG_BACKGROUND_NOTIFICATION;
180 case RunningLockType::RUNNINGLOCK_BACKGROUND_AUDIO:
181 return RUNNINGLOCK_TAG_BACKGROUND_AUDIO;
182 case RunningLockType::RUNNINGLOCK_BACKGROUND_SPORT:
183 return RUNNINGLOCK_TAG_BACKGROUND_SPORT;
184 case RunningLockType::RUNNINGLOCK_BACKGROUND_NAVIGATION:
185 return RUNNINGLOCK_TAG_BACKGROUND_NAVIGATION;
186 case RunningLockType::RUNNINGLOCK_BACKGROUND_TASK:
187 return RUNNINGLOCK_TAG_BACKGROUND_TASK;
188 default: {
189 HDF_LOGE("type=%{public}d is invalid, there is no corresponding tag", type);
190 return RUNNINGLOCK_TAG_BACKGROUND_INVALID;
191 }
192 }
193 }
194 } // namespace V1_1
195 } // namespace Power
196 } // namespace HDI
197 } // namespace OHOS
198