• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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 "res_sched_exe_mgr.h"
17 
18 #include <cinttypes>
19 #include <csignal>
20 #include <fstream>
21 #include <map>
22 #include <sstream>
23 
24 #include "cgroup_action.h"
25 #include "hitrace_meter.h"
26 
27 #include "plugin_mgr.h"
28 #include "res_exe_type.h"
29 #include "res_sched_exe_constants.h"
30 #include "res_sched_exe_log.h"
31 #include "directory_ex.h"
32 
33 namespace OHOS {
34 namespace ResourceSchedule {
35 namespace {
36     constexpr int32_t SIGNAL_KILL = 9;
37     const int32_t MAX_CONFIG_SIZE = 1024 * 1024;
38     const std::string STR_CONFIG_READER = "config";
39     const std::string STR_PLUGIN_SWITCH = "switch";
40 
41     const std::map<uint32_t, std::string> resTypeToStr = {
42         { ResExeType::RES_TYPE_COMMON_SYNC, "RES_TYPE_COMMON_SYNC" },
43         { ResExeType::RES_TYPE_COMMON_ASYNC, "RES_TYPE_COMMON_ASYNC" },
44         { ResExeType::RES_TYPE_THERMAL_AWARE_SYNC_EVENT, "THERMAL_AWARE_SYNC_EVENT" },
45         { ResExeType::RES_TYPE_THERMAL_AWARE_ASYNC_EVENT, "THERMAL_AWARE_ASYNC_EVENT" },
46         { ResExeType::RES_TYPE_SOCK_EXECUTOR_ASYNC_EVENT, "SOCK_EXECUTOR_ASYNC_EVENT" },
47         { ResExeType::RES_TYPE_DEBUG, "DEBUG_COMMAND" },
48     };
49 }
50 
51 IMPLEMENT_SINGLE_INSTANCE(ResSchedExeMgr);
52 
Init()53 void ResSchedExeMgr::Init()
54 {
55     PluginMgr::GetInstance().Init(true);
56     PluginMgr::GetInstance().SetResTypeStrMap(resTypeToStr);
57 }
58 
Stop()59 void ResSchedExeMgr::Stop()
60 {
61     PluginMgr::GetInstance().Stop();
62 }
63 
SendRequestSync(uint32_t resType,int64_t value,const nlohmann::json & payload,nlohmann::json & reply)64 int32_t ResSchedExeMgr::SendRequestSync(uint32_t resType, int64_t value,
65     const nlohmann::json& payload, nlohmann::json& reply)
66 {
67     RSSEXE_LOGD("receive resType = %{public}u, value = %{public}lld.", resType, (long long)value);
68     std::string traceStr = BuildTraceStr(__func__, resType, value);
69     HitraceScoped hitrace(HITRACE_TAG_OHOS, traceStr);
70     switch (resType) {
71         case ResExeType::RES_TYPE_EXECUTOR_PLUGIN_INIT:
72             InitPluginMgr(payload);
73             break;
74         case ResExeType::RES_TYPE_CGROUP_SYNC_EVENT:
75         case ResExeType::RES_TYPE_CGROUP_PROC_TASK_SYNC_EVENT:
76         case ResExeType::RES_TYPE_SET_THREAD_SCHED_POLICY_SYNC_EVENT:
77         case ResExeType::RES_TYPE_SET_THREAD_GROUP_SCHED_POLICY_SYNC_EVENT:
78             HandleRequestForCgroup(resType, payload, reply);
79             break;
80         default:
81             auto resData = std::make_shared<ResData>(resType, value, payload, reply);
82             int32_t ret = PluginMgr::GetInstance().DeliverResource(resData);
83             if (ret != ResIpcErrCode::RSSEXE_PLUGIN_ERROR) {
84                 reply["retCode"] = std::to_string(ret);
85             }
86             break;
87     }
88     return ResErrCode::RSSEXE_NO_ERR;
89 }
90 
SendRequestAsync(uint32_t resType,int64_t value,const nlohmann::json & payload)91 void ResSchedExeMgr::SendRequestAsync(uint32_t resType, int64_t value, const nlohmann::json& payload)
92 {
93     RSSEXE_LOGD("receive resType = %{public}u, value = %{public}lld.", resType, (long long)value);
94     if (resType == ResExeType::RES_TYPE_EXECUTOR_PLUGIN_INIT) {
95         InitPluginMgr(payload);
96         return;
97     }
98     std::string traceStr = BuildTraceStr(__func__, resType, value);
99     HitraceScoped hitrace(HITRACE_TAG_OHOS, traceStr);
100     PluginMgr::GetInstance().DispatchResource(std::make_shared<ResData>(resType, value, payload));
101 }
102 
KillProcess(pid_t pid)103 int32_t ResSchedExeMgr::KillProcess(pid_t pid)
104 {
105     int32_t killRes = kill(pid, SIGNAL_KILL);
106     return killRes;
107 }
108 
InitPluginMgr(const nlohmann::json & payload)109 void ResSchedExeMgr::InitPluginMgr(const nlohmann::json& payload)
110 {
111     if (isInit) {
112         RSSEXE_LOGE("plugin manager has init");
113         return;
114     }
115 
116     if (!payload.contains(STR_CONFIG_READER) || !payload[STR_CONFIG_READER].is_array()
117         || !payload.contains(STR_PLUGIN_SWITCH) || !payload[STR_PLUGIN_SWITCH].is_array()) {
118         RSSEXE_LOGE("recieve config string error");
119         return;
120     }
121 
122     isInit = true;
123     std::vector<std::string> configStrs = payload[STR_CONFIG_READER].get<std::vector<std::string>>();
124     std::vector<std::string> switchStrs = payload[STR_PLUGIN_SWITCH].get<std::vector<std::string>>();
125     for (auto configStr : configStrs) {
126         if (configStr.size() > MAX_CONFIG_SIZE) {
127             RSSEXE_LOGE("recieve config string too large");
128             return;
129         }
130     }
131     PluginMgr::GetInstance().ParseConfigReader(configStrs);
132 
133     for (auto switchStr : switchStrs) {
134         if (switchStr.size() > MAX_CONFIG_SIZE) {
135             RSSEXE_LOGE("recieve switch config string too large");
136             return;
137         }
138     }
139     PluginMgr::GetInstance().ParsePluginSwitch(switchStrs, true);
140     RSSEXE_LOGD("plugin manager init succeed");
141 }
142 
BuildTraceStr(const std::string & func,uint32_t resType,int64_t value)143 std::string ResSchedExeMgr::BuildTraceStr(const std::string& func, uint32_t resType, int64_t value)
144 {
145     std::string trace_str(func);
146     trace_str.append(",resType[").append(std::to_string(resType)).append("]");
147     trace_str.append(",value[").append(std::to_string(value)).append("]");
148     return trace_str;
149 }
150 
HandleRequestForCgroup(uint32_t resType,const nlohmann::json & payload,nlohmann::json & reply)151 void ResSchedExeMgr::HandleRequestForCgroup(uint32_t resType, const nlohmann::json& payload, nlohmann::json& reply)
152 {
153     if (resType != ResExeType::RES_TYPE_CGROUP_SYNC_EVENT &&
154         resType != ResExeType::RES_TYPE_CGROUP_PROC_TASK_SYNC_EVENT &&
155         resType != ResExeType::RES_TYPE_SET_THREAD_SCHED_POLICY_SYNC_EVENT &&
156         resType != ResExeType::RES_TYPE_SET_THREAD_GROUP_SCHED_POLICY_SYNC_EVENT) {
157         return;
158     }
159 
160     int tid;
161     CgroupSetting::SchedPolicy schedPolicy;
162     if (resType == ResExeType::RES_TYPE_SET_THREAD_SCHED_POLICY_SYNC_EVENT ||
163         resType == ResExeType::RES_TYPE_SET_THREAD_GROUP_SCHED_POLICY_SYNC_EVENT) {
164         int policy;
165         if (!(ParseValue(tid, "tid", payload)) || !(ParseValue(policy, "policy", payload))) {
166             RSSEXE_LOGE("%{public}s : ParseValue failed", __func__);
167             return;
168         }
169         schedPolicy = CgroupSetting::SchedPolicy(policy);
170     }
171 
172     int ret = 0;
173     switch (resType) {
174         case ResExeType::RES_TYPE_CGROUP_SYNC_EVENT:
175             GetCgroupFileContent(resType, payload, reply);
176             break;
177         case ResExeType::RES_TYPE_CGROUP_PROC_TASK_SYNC_EVENT:
178             CheckProcTaskForCgroup(resType, payload, reply);
179             break;
180         case ResExeType::RES_TYPE_SET_THREAD_SCHED_POLICY_SYNC_EVENT:
181             ret = CgroupSetting::CgroupAction::GetInstance().SetThreadSchedPolicy(tid, schedPolicy) ? 0 : -1;
182             reply["ret"] = std::to_string(ret);
183             break;
184         case ResExeType::RES_TYPE_SET_THREAD_GROUP_SCHED_POLICY_SYNC_EVENT:
185             ret = CgroupSetting::CgroupAction::GetInstance().SetThreadGroupSchedPolicy(tid, schedPolicy) ? 0 : -1;
186             reply["ret"] = std::to_string(ret);
187             break;
188         default:
189             break;
190     }
191     return;
192 }
193 
ParseValue(int32_t & value,const char * name,const nlohmann::json & payload)194 bool ResSchedExeMgr::ParseValue(int32_t& value, const char* name, const nlohmann::json& payload)
195 {
196     if (payload.contains(name) && payload.at(name).is_string()) {
197         value = atoi(payload[name].get<std::string>().c_str());
198         return true;
199     }
200     return false;
201 }
202 
GetCgroupFileContent(uint32_t resType,const nlohmann::json & payload,nlohmann::json & reply)203 void ResSchedExeMgr::GetCgroupFileContent(uint32_t resType, const nlohmann::json& payload, nlohmann::json& reply)
204 {
205     if (!payload.contains("pid") || !payload["pid"].is_number_integer()) {
206         return;
207     }
208     int pid = payload["pid"];
209     std::string path = std::string("/proc/").append(std::to_string(pid)).append("/cgroup");
210     char resolvedPath[PATH_MAX] = { 0 };
211     if (path.size() > PATH_MAX || !realpath(path.c_str(), resolvedPath)) {
212         RSSEXE_LOGE("%{public}s realpath failed", __func__);
213         return;
214     }
215     auto realPath = std::string(resolvedPath);
216     std::ifstream fin(realPath.c_str(), std::ios::in);
217     if (!fin) {
218         return;
219     }
220     std::stringstream ss;
221     ss << fin.rdbuf();
222     reply["res"] = ss.str();
223 }
224 
CheckProcTaskForCgroup(uint32_t resType,const nlohmann::json & payload,nlohmann::json & reply)225 void ResSchedExeMgr::CheckProcTaskForCgroup(uint32_t resType, const nlohmann::json& payload, nlohmann::json& reply)
226 {
227     if (!payload.contains("pid") || !payload["pid"].is_number_integer()) {
228         return;
229     }
230     if (!payload.contains("tid") || !payload["tid"].is_number_integer()) {
231         return;
232     }
233     int pid = payload["pid"];
234     int tid = payload["tid"];
235     std::string pathName = std::string("/proc/").append(std::to_string(pid))
236         .append("/task/").append(std::to_string(tid)).append("/comm");
237     std::string realPath;
238     reply["res"] = PathToRealPath(pathName, realPath);
239     return;
240 }
241 } // namespace ResourceSchedule
242 } // namespace OHOS
243