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_2 {
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 const std::string RUNNINGLOCK_TAG_BACKGROUND_PHONEEXT = "OHOS.RunningLock.Background.PhoneExt";
35 constexpr int32_t DEFAULT_TIMEOUT = 3000;
36 } // namespace
37 std::mutex RunningLockImpl::mutex_;
38 int32_t RunningLockImpl::defaultTimeOutMs_ = DEFAULT_TIMEOUT;
39 std::unique_ptr<RunningLockTimerHandler> RunningLockImpl::timerHandler_ = nullptr;
40 std::map<RunningLockType, std::shared_ptr<RunningLockCounter>> RunningLockImpl::lockCounters_ = {};
41 sptr<IPowerRunningLockCallback> g_iPowerRunningLockCallback = nullptr;
42
Hold(const RunningLockInfo & info,PowerHdfState state,uint64_t lockid,const std::string & bundleName)43 int32_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
Unhold(const RunningLockInfo & info,uint64_t lockid,const std::string & bundleName)81 int32_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
HoldLock(const RunningLockInfo & info,PowerHdfState state,uint64_t lockid,const std::string & bundleName)110 int32_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
UnholdLock(const RunningLockInfo & info,uint64_t lockid,const std::string & bundleName)122 int32_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
Clean()134 void 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
GetCount(RunningLockType type)150 uint32_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
SetDefaultTimeOutMs(int32_t timeOutMs)161 void RunningLockImpl::SetDefaultTimeOutMs(int32_t timeOutMs)
162 {
163 std::lock_guard<std::mutex> lock(mutex_);
164 if (timeOutMs > 0) {
165 defaultTimeOutMs_ = timeOutMs;
166 }
167 }
168
IsValidType(RunningLockType type,PowerHdfState state)169 bool 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
FillRunningLockInfo(const RunningLockInfo & info)184 RunningLockInfo 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
GetRunningLockTag(RunningLockType type)202 std::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
GetRunningLockTagInner(RunningLockType type)224 std::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
RegisterRunningLockCallback(const sptr<IPowerRunningLockCallback> & iPowerRunningLockCallback)246 void 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
UnRegisterRunningLockCallback()254 void RunningLockImpl::UnRegisterRunningLockCallback()
255 {
256 std::lock_guard<std::mutex> lock(mutex_);
257 g_iPowerRunningLockCallback = nullptr;
258 HDF_LOGI("UnRegisterRunningLockCallback success");
259 }
260
NotifyChanged(const RunningLockInfo & info,const uint64_t & lockid,const std::string & bundleName,const std::string & tag)261 void 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