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_proxy.h"
17 #include "power_mgr_service.h"
18
19 #include <cmath>
20 #include "power_log.h"
21
22 namespace OHOS {
23 namespace PowerMgr {
24 namespace {
25 static const std::string OFFLOAD_RUNNING_NAME = "AudioOffloadBackgroudPlay";
26 }
AddRunningLock(pid_t pid,pid_t uid,const sptr<IRemoteObject> & remoteObj)27 void RunningLockProxy::AddRunningLock(pid_t pid, pid_t uid, const sptr<IRemoteObject>& remoteObj)
28 {
29 std::string proxyKey = AssembleProxyKey(pid, uid);
30 auto proxyIter = proxyMap_.find(proxyKey);
31 WksMap wksMap;
32 if (proxyIter == proxyMap_.end()) {
33 TokenWorkSourceMap tokenWksMap;
34 tokenWksMap.emplace(remoteObj, std::make_pair(wksMap, 0));
35 proxyMap_.emplace(proxyKey, tokenWksMap);
36 POWER_HILOGD(FEATURE_RUNNING_LOCK, "Add runninglock proxy, proxyKey=%{public}s", proxyKey.c_str());
37 } else {
38 auto& tokenWksMap = proxyIter->second;
39 auto tokenIter = tokenWksMap.find(remoteObj);
40 if (tokenIter == tokenWksMap.end()) {
41 tokenWksMap.emplace(remoteObj, std::make_pair(wksMap, 0));
42 POWER_HILOGD(FEATURE_RUNNING_LOCK, "Insert runninglock, proxyKey=%{public}s", proxyKey.c_str());
43 } else {
44 POWER_HILOGD(FEATURE_RUNNING_LOCK, "Already add runninglock, proxyKey=%{public}s", proxyKey.c_str());
45 }
46 }
47 }
48
RemoveRunningLock(pid_t pid,pid_t uid,const sptr<IRemoteObject> & remoteObj)49 void RunningLockProxy::RemoveRunningLock(pid_t pid, pid_t uid, const sptr<IRemoteObject>& remoteObj)
50 {
51 std::string proxyKey = AssembleProxyKey(pid, uid);
52 auto proxyIter = proxyMap_.find(proxyKey);
53 if (proxyIter == proxyMap_.end()) {
54 POWER_HILOGI(FEATURE_RUNNING_LOCK,
55 "Runninglock proxyKey is not existed, proxyKey=%{public}s", proxyKey.c_str());
56 return;
57 }
58 TokenWorkSourceMap& tokenWksMap = proxyIter->second;
59 auto tokenIter = tokenWksMap.find(remoteObj);
60 if (tokenIter == tokenWksMap.end()) {
61 POWER_HILOGD(FEATURE_RUNNING_LOCK, "Runninglock is not existed, proxyKey=%{public}s", proxyKey.c_str());
62 return;
63 } else {
64 tokenWksMap.erase(tokenIter);
65 POWER_HILOGD(FEATURE_RUNNING_LOCK, "Runninglocklist empty, earse proxyKey=%{public}s", proxyKey.c_str());
66 }
67 if (proxyIter->second.empty()) {
68 proxyMap_.erase(proxyIter);
69 POWER_HILOGD(FEATURE_RUNNING_LOCK, "Runninglocklist empty, earse proxyKey=%{public}s", proxyKey.c_str());
70 }
71 }
72
UpdateWorkSource(pid_t pid,pid_t uid,const sptr<IRemoteObject> & remoteObj,const std::map<int32_t,std::string> & workSources)73 bool RunningLockProxy::UpdateWorkSource(pid_t pid, pid_t uid, const sptr<IRemoteObject>& remoteObj,
74 const std::map<int32_t, std::string>& workSources)
75 {
76 std::string proxyKey = AssembleProxyKey(pid, uid);
77 auto proxyIter = proxyMap_.find(proxyKey);
78 if (proxyIter == proxyMap_.end()) {
79 POWER_HILOGW(FEATURE_RUNNING_LOCK, "UpdateWorkSource failed, proxyKey=%{public}s not existed",
80 proxyKey.c_str());
81 return false;
82 }
83 auto& tokenWksMap = proxyIter->second;
84 auto tokenWksMapIter = tokenWksMap.find(remoteObj);
85 if (tokenWksMapIter == tokenWksMap.end()) {
86 POWER_HILOGW(FEATURE_RUNNING_LOCK, "UpdateWorkSource failed, runninglock not existed");
87 return false;
88 }
89 auto& workSourceMap = tokenWksMapIter->second.first;
90 WksMap workSourcesState;
91 std::string bundleName;
92 int32_t proxyCount = 0;
93 for (const auto& wks : workSources) {
94 auto iter = workSourceMap.find(wks.first);
95 if (iter != workSourceMap.end()) {
96 workSourcesState.insert({ iter->first, { iter->second.first, iter->second.second } });
97 if (iter->second.second) {
98 proxyCount++;
99 } else {
100 bundleName.append(iter->second.first).append(" ");
101 }
102 } else {
103 workSourcesState.insert({ wks.first, { wks.second, false } });
104 bundleName.append(wks.second).append(" ");
105 }
106 }
107 if (!bundleName.empty()) {
108 bundleName.pop_back();
109 }
110 bool isProxyed = tokenWksMapIter->second.second != 0 &&
111 tokenWksMapIter->second.second == static_cast<int32_t>(workSourceMap.size());
112 int32_t wksCount = static_cast<int32_t>(workSourcesState.size());
113 if (isProxyed && wksCount > proxyCount) {
114 ProxyInner(remoteObj, bundleName, RunningLockEvent::RUNNINGLOCK_UNPROXY);
115 } else if (!isProxyed && wksCount > 0 && wksCount == proxyCount) {
116 ProxyInner(remoteObj, bundleName, RunningLockEvent::RUNNINGLOCK_PROXY);
117 } else {
118 ProxyInner(remoteObj, bundleName, RunningLockEvent::RUNNINGLOCK_UPDATE);
119 }
120 tokenWksMapIter->second.first = std::move(workSourcesState);
121 tokenWksMapIter->second.second = proxyCount;
122 return true;
123 }
124
ProxyInner(const sptr<IRemoteObject> & remoteObj,const std::string & bundleNames,RunningLockEvent event)125 void RunningLockProxy::ProxyInner(const sptr<IRemoteObject>& remoteObj,
126 const std::string& bundleNames, RunningLockEvent event)
127 {
128 auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
129 if (pms == nullptr) {
130 POWER_HILOGW(FEATURE_RUNNING_LOCK, "Power service is nullptr");
131 return;
132 }
133 auto rlmgr = pms->GetRunningLockMgr();
134 if (rlmgr == nullptr) {
135 POWER_HILOGW(FEATURE_RUNNING_LOCK, "RunninglockMgr is nullptr");
136 return;
137 }
138 auto lockInner = rlmgr->GetRunningLockInner(remoteObj);
139 if (lockInner == nullptr) {
140 POWER_HILOGW(FEATURE_RUNNING_LOCK, "RunninglockMgr is nullptr");
141 return;
142 }
143 lockInner->SetBundleName(bundleNames);
144 switch (event) {
145 case RunningLockEvent::RUNNINGLOCK_UPDATE:
146 rlmgr->NotifyRunningLockChanged(lockInner->GetParam(), "DUBAI_TAG_RUNNINGLOCK_UPDATE");
147 break;
148 case RunningLockEvent::RUNNINGLOCK_PROXY:
149 rlmgr->NotifyRunningLockChanged(lockInner->GetParam(), "DUBAI_TAG_RUNNINGLOCK_UPDATE");
150 rlmgr->UnlockInnerByProxy(remoteObj, lockInner);
151 break;
152 case RunningLockEvent::RUNNINGLOCK_UNPROXY:
153 rlmgr->LockInnerByProxy(remoteObj, lockInner);
154 rlmgr->NotifyRunningLockChanged(lockInner->GetParam(), "DUBAI_TAG_RUNNINGLOCK_UPDATE");
155 break;
156 default:
157 break;
158 }
159 }
160
GetRunningLockName(const sptr<IRemoteObject> & remoteObj)161 std::string RunningLockProxy::GetRunningLockName(const sptr<IRemoteObject>& remoteObj)
162 {
163 auto pms = DelayedSpSingleton<PowerMgrService>::GetInstance();
164 if (pms == nullptr) {
165 POWER_HILOGW(FEATURE_RUNNING_LOCK, "Power service is nullptr");
166 return "";
167 }
168 auto rlmgr = pms->GetRunningLockMgr();
169 if (rlmgr == nullptr) {
170 POWER_HILOGW(FEATURE_RUNNING_LOCK, "RunninglockMgr is nullptr");
171 return "";
172 }
173 auto lockInner = rlmgr->GetRunningLockInner(remoteObj);
174 if (lockInner == nullptr) {
175 POWER_HILOGW(FEATURE_RUNNING_LOCK, "RunninglockMgr is nullptr");
176 return "";
177 }
178 return lockInner->GetName();
179 }
180
MergeBundleName(const WksMap & wksMap)181 std::string RunningLockProxy::MergeBundleName(const WksMap& wksMap)
182 {
183 std::string bundleName;
184 for (const auto& wks : wksMap) {
185 if (wks.second.second == false) {
186 bundleName.append(wks.second.first).append(" ");
187 }
188 }
189 if (!bundleName.empty()) {
190 bundleName.pop_back();
191 }
192 return bundleName;
193 }
194
IncreaseProxyCnt(pid_t pid,pid_t uid)195 bool RunningLockProxy::IncreaseProxyCnt(pid_t pid, pid_t uid)
196 {
197 std::string proxyKey = AssembleProxyKey(pid, uid);
198 POWER_HILOGI(FEATURE_RUNNING_LOCK, "IncreaseProxyCnt proxykey=%{public}s", proxyKey.c_str());
199 auto proxyIter = proxyMap_.find(proxyKey);
200 if (proxyIter != proxyMap_.end()) {
201 auto& tokenWksMap = proxyIter->second;
202 for (auto& tokenWksItem : tokenWksMap) {
203 for (auto& wks : tokenWksItem.second.first) {
204 wks.second.second = true;
205 }
206 tokenWksItem.second.second = static_cast<int32_t>(tokenWksItem.second.first.size());
207 ProxyInner(tokenWksItem.first, "", RunningLockEvent::RUNNINGLOCK_PROXY);
208 }
209 }
210 for (auto& proxyItem : proxyMap_) {
211 auto& tokenWksMap = proxyItem.second;
212 for (auto& tokenWksItem : tokenWksMap) {
213 if (GetRunningLockName(tokenWksItem.first).find(OFFLOAD_RUNNING_NAME) != std::string::npos) {
214 POWER_HILOGD(FEATURE_RUNNING_LOCK, "AudioOffloadBackgroudPlay runninglock skip");
215 continue;
216 }
217 auto& wksMap = tokenWksItem.second.first;
218 if (wksMap.find(uid) != wksMap.end() && !wksMap[uid].second) {
219 wksMap[uid].second = true;
220 tokenWksItem.second.second++;
221 } else {
222 continue;
223 }
224 if (tokenWksItem.second.second == static_cast<int32_t>(wksMap.size())) {
225 ProxyInner(tokenWksItem.first, "", RunningLockEvent::RUNNINGLOCK_PROXY);
226 } else {
227 ProxyInner(tokenWksItem.first, MergeBundleName(wksMap), RunningLockEvent::RUNNINGLOCK_UPDATE);
228 }
229 }
230 }
231 return true;
232 }
233
DecreaseProxyCnt(pid_t pid,pid_t uid)234 bool RunningLockProxy::DecreaseProxyCnt(pid_t pid, pid_t uid)
235 {
236 std::string proxyKey = AssembleProxyKey(pid, uid);
237 POWER_HILOGI(FEATURE_RUNNING_LOCK, "DecreaseProxyCnt proxykey=%{public}s", proxyKey.c_str());
238 auto proxyIter = proxyMap_.find(proxyKey);
239 if (proxyIter != proxyMap_.end()) {
240 auto& tokenWksMap = proxyIter->second;
241 for (auto& tokenWksItem : tokenWksMap) {
242 for (auto& wks : tokenWksItem.second.first) {
243 wks.second.second = false;
244 }
245 tokenWksItem.second.second = 0;
246 ProxyInner(tokenWksItem.first, MergeBundleName(tokenWksItem.second.first),
247 RunningLockEvent::RUNNINGLOCK_UNPROXY);
248 }
249 }
250 for (auto& proxyItem : proxyMap_) {
251 auto& tokenWksMap = proxyItem.second;
252 for (auto& tokenWksItem : tokenWksMap) {
253 if (GetRunningLockName(tokenWksItem.first).find(OFFLOAD_RUNNING_NAME) != std::string::npos) {
254 POWER_HILOGD(FEATURE_RUNNING_LOCK, "AudioOffloadBackgroudPlay runninglock skip");
255 continue;
256 }
257 auto& wksMap = tokenWksItem.second.first;
258 if (wksMap.find(uid) != wksMap.end() && wksMap[uid].second) {
259 wksMap[uid].second = false;
260 tokenWksItem.second.second = std::max(0, tokenWksItem.second.second - 1);
261 } else {
262 continue;
263 }
264 if (tokenWksItem.second.second == static_cast<int32_t>(wksMap.size()) - 1) {
265 ProxyInner(tokenWksItem.first, MergeBundleName(wksMap), RunningLockEvent::RUNNINGLOCK_UNPROXY);
266 } else {
267 ProxyInner(tokenWksItem.first, MergeBundleName(wksMap), RunningLockEvent::RUNNINGLOCK_UPDATE);
268 }
269 }
270 }
271 return true;
272 }
273
DumpProxyInfo()274 std::string RunningLockProxy::DumpProxyInfo()
275 {
276 std::string result {""};
277 int index = 0;
278 for (const auto& [key, value] : proxyMap_) {
279 index++;
280 result.append(" ProcessIndex=").append(std::to_string(index))
281 .append(" pid_uid=").append(key)
282 .append(" lock_cnt=").append(std::to_string(value.size())).append("\n");
283 int lockIndex = 0;
284 for (const auto& [token, tokenWksMap] : value) {
285 lockIndex++;
286 result.append("****lockIndex=").append(std::to_string(lockIndex))
287 .append("****workSourceSize=").append(std::to_string(tokenWksMap.first.size()))
288 .append("****proxyCount=").append(std::to_string(tokenWksMap.second))
289 .append("\n");
290 int appIndex = 0;
291 for (const auto& wks : tokenWksMap.first) {
292 appIndex++;
293 result.append("********workSourceIndex=").append(std::to_string(appIndex))
294 .append("********appuid=").append(std::to_string(wks.first))
295 .append("********bundleName=").append(wks.second.first)
296 .append("********proxyState=").append(std::to_string(wks.second.second))
297 .append("\n");
298 }
299 }
300 }
301 return result;
302 }
303
ResetRunningLocks()304 void RunningLockProxy::ResetRunningLocks()
305 {
306 POWER_HILOGI(FEATURE_RUNNING_LOCK, "reset proxycnt");
307 for (auto &proxyItem : proxyMap_) {
308 auto& tokenWksMap = proxyItem.second;
309 for (auto &tokenWksItem : tokenWksMap) {
310 for (auto &wks : tokenWksItem.second.first) {
311 wks.second.second = false;
312 }
313 ProxyInner(tokenWksItem.first, MergeBundleName(tokenWksItem.second.first),
314 RunningLockEvent::RUNNINGLOCK_UNPROXY);
315 tokenWksItem.second.second = 0;
316 }
317 }
318 }
319
UpdateProxyState(pid_t pid,pid_t uid,const sptr<IRemoteObject> & remoteObj,bool state)320 bool RunningLockProxy::UpdateProxyState(pid_t pid, pid_t uid, const sptr<IRemoteObject>& remoteObj,
321 bool state)
322 {
323 std::string proxyKey = AssembleProxyKey(pid, uid);
324 auto proxyIter = proxyMap_.find(proxyKey);
325 if (proxyIter == proxyMap_.end()) {
326 POWER_HILOGW(FEATURE_RUNNING_LOCK, "UpdateProxyState failed, proxyKey=%{public}s not existed",
327 proxyKey.c_str());
328 return false;
329 }
330 auto& tokenWksMap = proxyIter->second;
331 auto tokenWksMapIter = tokenWksMap.find(remoteObj);
332 if (tokenWksMapIter == tokenWksMap.end()) {
333 POWER_HILOGW(FEATURE_RUNNING_LOCK, "UpdateProxyState failed, runninglock not existed");
334 return false;
335 }
336 auto& workSourceMap = tokenWksMapIter->second.first;
337 for (auto &wks : workSourceMap) {
338 wks.second.second = false;
339 }
340 tokenWksMapIter->second.second = 0;
341 return true;
342 }
343
Clear()344 void RunningLockProxy::Clear()
345 {
346 proxyMap_.clear();
347 }
348
AssembleProxyKey(pid_t pid,pid_t uid)349 std::string RunningLockProxy::AssembleProxyKey(pid_t pid, pid_t uid)
350 {
351 return std::to_string(pid) + "_" + std::to_string(uid);
352 }
353 } // namespace PowerMgr
354 } // namespace OHOS
355
356