1 /*
2  * Copyright (c) 2022 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 "supervisor.h"
17 #include "ability_info.h"
18 #include "cgroup_sched_common.h"
19 #include "if_system_ability_manager.h"
20 #include "iservice_registry.h"
21 #include "system_ability_definition.h"
22 #include "cgroup_sched_log.h"
23 
24 namespace OHOS {
25 namespace ResourceSchedule {
26 using OHOS::AppExecFwk::AbilityType;
27 
GetAbilityInfoNonNull(uintptr_t token)28 std::shared_ptr<AbilityInfo> ProcessRecord::GetAbilityInfoNonNull(uintptr_t token)
29 {
30     auto a = std::find_if(abilities_.begin(), abilities_.end(), [ token ] (const auto& a) {
31         return a->token_ == token;
32     });
33     if (a != abilities_.end()) {
34         return *a;
35     }
36     std::shared_ptr<AbilityInfo> abi = std::make_shared<AbilityInfo>(token);
37     abilities_.push_back(abi);
38     return abi;
39 }
40 
GetAbilityInfo(uintptr_t token)41 std::shared_ptr<AbilityInfo> ProcessRecord::GetAbilityInfo(uintptr_t token)
42 {
43     auto a = std::find_if(abilities_.begin(), abilities_.end(), [ token ] (const auto& a) {
44         return a->token_ == token;
45     });
46     if (a != abilities_.end()) {
47         return *a;
48     }
49     return nullptr;
50 }
51 
GetWindowInfoNonNull(uint32_t windowId)52 std::shared_ptr<WindowInfo> ProcessRecord::GetWindowInfoNonNull(uint32_t windowId)
53 {
54     auto w = std::find_if(windows_.begin(), windows_.end(), [ windowId ] (const auto& w) {
55         return w->windowId_ == windowId;
56     });
57     if (w != windows_.end()) {
58         return *w;
59     }
60     std::shared_ptr<WindowInfo> win = std::make_shared<WindowInfo>(windowId);
61     windows_.push_back(win);
62     return win;
63 }
64 
RemoveAbilityByToken(uintptr_t token)65 void ProcessRecord::RemoveAbilityByToken(uintptr_t token)
66 {
67     for (auto iter = abilities_.begin(); iter != abilities_.end(); ++iter) {
68         if ((*iter)->token_ == token) {
69             abilities_.erase(iter);
70             break;
71         }
72     }
73 }
74 
HasAbility(uintptr_t token) const75 bool ProcessRecord::HasAbility(uintptr_t token) const
76 {
77     return std::any_of(abilities_.begin(), abilities_.end(), [ token ] (const auto& abi) {
78         return abi->token_ == token;
79     });
80 }
81 
HasServiceExtension() const82 bool ProcessRecord::HasServiceExtension() const
83 {
84     return std::any_of(abilities_.begin(), abilities_.end(), [] (const auto& abi) {
85         return abi->type_ == (int32_t)(AbilityType::SERVICE)
86             || abi->type_ == (int32_t)(AbilityType::EXTENSION)
87             || abi->type_ == (int32_t)(AbilityType::DATA);
88     });
89 }
90 
IsVisible() const91 bool ProcessRecord::IsVisible() const
92 {
93     return std::any_of(windows_.begin(), windows_.end(), [] (const auto& w) {
94         return w->isVisible_;
95     });
96 }
97 
GetKeyTidSetByRole(int64_t role)98 std::set<int32_t> ProcessRecord::GetKeyTidSetByRole(int64_t role)
99 {
100     std::set<int32_t> tids {};
101     for (const auto [tid, tidRole] : keyThreadRoleMap_) {
102         if (tidRole != role) {
103             continue;
104         }
105         tids.insert(tid);
106     }
107     return tids;
108 }
109 
AddProcessRecord(std::shared_ptr<ProcessRecord> pr)110 std::shared_ptr<ProcessRecord> Application::AddProcessRecord(std::shared_ptr<ProcessRecord> pr)
111 {
112     if (pr) {
113         pidsMap_[pr->GetPid()] = pr;
114     }
115     return pr;
116 }
117 
RemoveProcessRecord(pid_t pid)118 void Application::RemoveProcessRecord(pid_t pid)
119 {
120     auto iter = pidsMap_.find(pid);
121     if (iter != pidsMap_.end()) {
122         if (focusedProcess_ == iter->second) {
123             focusedProcess_ = nullptr;
124         }
125         if (IsHostProcess(pid)) {
126             hostPidsSet_.erase(pid);
127         }
128         pidsMap_.erase(iter);
129     }
130 }
131 
GetProcessRecord(pid_t pid)132 std::shared_ptr<ProcessRecord> Application::GetProcessRecord(pid_t pid)
133 {
134     auto iter = pidsMap_.find(pid);
135     if (iter != pidsMap_.end()) {
136         return iter->second;
137     }
138     return nullptr;
139 }
140 
GetProcessRecordNonNull(pid_t pid)141 std::shared_ptr<ProcessRecord> Application::GetProcessRecordNonNull(pid_t pid)
142 {
143     auto iter = pidsMap_.find(pid);
144     if (iter != pidsMap_.end()) {
145         return iter->second;
146     }
147     auto pr = std::make_shared<ProcessRecord>(this->GetUid(), pid);
148     pidsMap_[pid] = pr;
149     return pr;
150 }
151 
FindProcessRecordByToken(uintptr_t token)152 std::shared_ptr<ProcessRecord> Application::FindProcessRecordByToken(uintptr_t token)
153 {
154     for (auto iter = pidsMap_.begin(); iter != pidsMap_.end(); iter++) {
155         auto pr = iter->second;
156         if (pr->HasAbility(token)) {
157             return pr;
158         }
159     }
160     return nullptr;
161 }
162 
SetName(const std::string & name)163 void Application::SetName(const std::string& name)
164 {
165     if (name_.empty()) {
166         name_ = name;
167     }
168 }
169 
FindProcessRecordByWindowId(uint32_t windowId)170 std::shared_ptr<ProcessRecord> Application::FindProcessRecordByWindowId(uint32_t windowId)
171 {
172     for (auto iter = pidsMap_.begin(); iter != pidsMap_.end(); iter++) {
173         auto pr = iter->second;
174         if (std::any_of(pr->windows_.begin(), pr->windows_.end(),
175             [ windowId ] (const auto& w) {
176                 return w->windowId_ == windowId;
177             })) {
178             return pr;
179         }
180     }
181     return nullptr;
182 }
183 
AddHostProcess(int32_t hostPid)184 void Application::AddHostProcess(int32_t hostPid)
185 {
186     hostPidsSet_.insert(hostPid);
187 }
188 
IsHostProcess(int32_t hostPid) const189 bool Application::IsHostProcess(int32_t hostPid) const
190 {
191     if (hostPidsSet_.find(hostPid) != hostPidsSet_.end()) {
192         return true;
193     } else {
194         return false;
195     }
196 }
197 
GetAppRecord(int32_t uid)198 std::shared_ptr<Application> Supervisor::GetAppRecord(int32_t uid)
199 {
200     auto iter = uidsMap_.find(uid);
201     if (iter != uidsMap_.end()) {
202         return iter->second;
203     }
204     return nullptr;
205 }
206 
GetAppRecordNonNull(int32_t uid)207 std::shared_ptr<Application> Supervisor::GetAppRecordNonNull(int32_t uid)
208 {
209     auto iter = uidsMap_.find(uid);
210     if (iter != uidsMap_.end()) {
211         return iter->second;
212     }
213     auto app = std::make_shared<Application>(uid);
214     uidsMap_[uid] = app;
215     return app;
216 }
217 
FindProcessRecord(pid_t pid)218 std::shared_ptr<ProcessRecord> Supervisor::FindProcessRecord(pid_t pid)
219 {
220     std::shared_ptr<ProcessRecord> pr = nullptr;
221     for (auto iter = uidsMap_.begin(); iter != uidsMap_.end(); iter++) {
222         auto app = iter->second;
223         pr = app->GetProcessRecord(pid);
224         if (pr) {
225             break;
226         }
227     }
228     return pr;
229 }
230 
RemoveApplication(int32_t uid)231 void Supervisor::RemoveApplication(int32_t uid)
232 {
233     auto iter = uidsMap_.find(uid);
234     if (iter != uidsMap_.end()) {
235         uidsMap_.erase(iter);
236     }
237 }
238 
SearchAbilityToken(std::shared_ptr<Application> & application,std::shared_ptr<ProcessRecord> & procRecord,uintptr_t token)239 void Supervisor::SearchAbilityToken(std::shared_ptr<Application> &application,
240     std::shared_ptr<ProcessRecord> &procRecord, uintptr_t token)
241 {
242     std::shared_ptr<ProcessRecord> pr = nullptr;
243     for (auto iter = uidsMap_.begin(); iter != uidsMap_.end(); iter++) {
244         auto app = iter->second;
245         pr = app->FindProcessRecordByToken(token);
246         if (pr) {
247             application = app;
248             procRecord = pr;
249             break;
250         }
251     }
252 }
253 
SearchWindowId(std::shared_ptr<Application> & application,std::shared_ptr<ProcessRecord> & procRecord,uint32_t windowId)254 void Supervisor::SearchWindowId(std::shared_ptr<Application> &application,
255     std::shared_ptr<ProcessRecord> &procRecord, uint32_t windowId)
256 {
257     std::shared_ptr<ProcessRecord> pr = nullptr;
258     for (auto iter = uidsMap_.begin(); iter != uidsMap_.end(); iter++) {
259         auto app = iter->second;
260         pr = app->FindProcessRecordByWindowId(windowId);
261         if (pr) {
262             application = app;
263             procRecord = pr;
264             break;
265         }
266     }
267 }
268 
SetSystemLoadLevelState(int32_t level)269 void Supervisor::SetSystemLoadLevelState(int32_t level)
270 {
271     systemLoadLevel_ = level;
272 }
273 
GetSystemLoadLevel()274 int32_t Supervisor::GetSystemLoadLevel()
275 {
276     return systemLoadLevel_;
277 }
278 
ConnectAppManagerService()279 void Supervisor::ConnectAppManagerService()
280 {
281     sptr<OHOS::ISystemAbilityManager> systemAbilityManager =
282         OHOS::SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
283     sptr<OHOS::IRemoteObject> object = systemAbilityManager->GetSystemAbility(OHOS::APP_MGR_SERVICE_ID);
284     appManager_ = OHOS::iface_cast<OHOS::AppExecFwk::IAppMgr>(object);
285 }
286 
ReloadApplication()287 void Supervisor::ReloadApplication()
288 {
289     if (appManager_ == nullptr) {
290         return;
291     }
292     std::vector<AppExecFwk::RunningProcessInfo> runningProcess;
293     appManager_->GetAllRunningProcesses(runningProcess);
294     for (const auto& process : runningProcess) {
295         std::shared_ptr<Application> app = GetAppRecordNonNull(process.uid_);
296         if (process.bundleNames.size() != 0) {
297             app -> SetName(process.bundleNames[0]);
298         }
299         std::shared_ptr<ProcessRecord> procRecord = app->GetProcessRecordNonNull(process.pid_);
300         CGS_LOGI("reload application cache uid:%{public}d pid:%{public}d bundleName:%{public}s isFocused:%{public}d",
301             process.uid_, process.pid_, app->GetName().c_str(), process.isFocused);
302     }
303 }
304 
ReloadChildProcess()305 void Supervisor::ReloadChildProcess()
306 {
307     if (appManager_ == nullptr) {
308         return;
309     }
310     std::vector<AppExecFwk::ChildProcessInfo> childProcess;
311     appManager_->GetAllChildrenProcesses(childProcess);
312     for (const auto& process : childProcess) {
313         std::shared_ptr<Application> app = GetAppRecordNonNull(process.hostUid);
314         app->AddHostProcess(process.hostPid);
315         auto procRecord = app->GetProcessRecordNonNull(process.pid);
316         procRecord->processType_ = ProcRecordType::CHILD;
317         procRecord->hostPid_ = process.hostPid;
318         CGS_LOGI("reload child process bundleName:%{public}s processName:%{public}s pid:%{public}d \
319             uid:%{public}d hostUid:%{public}d hostPid:%{public}d",
320             process.bundleName.c_str(), process.processName.c_str(), process.pid,
321             process.uid, process.hostUid, process.hostPid);
322     }
323 }
324 
InitSuperVisorContent()325 void Supervisor::InitSuperVisorContent()
326 {
327     ConnectAppManagerService();
328     /* reload application info */
329     ReloadApplication();
330     /* reload child process*/
331     ReloadChildProcess();
332 }
333 } // namespace ResourceSchedule
334 } // namespace OHOS
335