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