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