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 "rtg_interface.h"
17 #include <sys/ioctl.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <securec.h>
21 #include <cstdio>
22 #include <string>
23 #include <vector>
24 #include <cerrno>
25 #include "bits/ioctl.h"
26 #include "rme_log_domain.h"
27
28 #undef LOG_TAG
29 #define LOG_TAG "rtg_interface"
30
31 namespace OHOS {
32 namespace RME {
33 namespace {
34 constexpr size_t MAX_LENGTH = 100;
35 }
36
37 const char RTG_SCHED_IPC_MAGIC = 0xAB;
38 static int g_fd = -1;
39
40 #define CMD_ID_SET_ENABLE \
41 _IOWR(RTG_SCHED_IPC_MAGIC, SET_ENABLE, struct rtg_enable_data)
42 #define CMD_ID_SET_RTG \
43 _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG, struct rtg_str_data)
44 #define CMD_ID_SET_CONFIG \
45 _IOWR(RTG_SCHED_IPC_MAGIC, SET_CONFIG, struct rtg_str_data)
46 #define CMD_ID_SET_RTG_ATTR \
47 _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG_ATTR, struct rtg_str_data)
48 #define CMD_ID_BEGIN_FRAME_FREQ \
49 _IOWR(RTG_SCHED_IPC_MAGIC, BEGIN_FRAME_FREQ, struct proc_state_data)
50 #define CMD_ID_END_FRAME_FREQ \
51 _IOWR(RTG_SCHED_IPC_MAGIC, END_FRAME_FREQ, struct proc_state_data)
52 #define CMD_ID_END_SCENE \
53 _IOWR(RTG_SCHED_IPC_MAGIC, END_SCENE, struct proc_state_data)
54 #define CMD_ID_SET_MIN_UTIL \
55 _IOWR(RTG_SCHED_IPC_MAGIC, SET_MIN_UTIL, struct proc_state_data)
56 #define CMD_ID_SET_MAX_UTIL \
57 _IOWR(RTG_SCHED_IPC_MAGIC, SET_MAX_UTIL, struct proc_state_data)
58 #define CMD_ID_SET_MARGIN \
59 _IOWR(RTG_SCHED_IPC_MAGIC, SET_MARGIN, struct proc_state_data)
60 #define CMD_ID_SEARCH_RTG \
61 _IOWR(RTG_SCHED_IPC_MAGIC, SEARCH_RTG, struct proc_state_data)
62 #define CMD_ID_GET_ENABLE \
63 _IOWR(RTG_SCHED_IPC_MAGIC, GET_ENABLE, struct rtg_enable_data)
64
BasicOpenRtgNode()65 __attribute__((constructor)) void BasicOpenRtgNode()
66 {
67 char fileName[] = "/proc/self/sched_rtg_ctrl";
68 FILE* fd = fopen(fileName, "r+");
69 if (fd == nullptr) {
70 RME_LOGI("rtg Open fail, errno = %{public}d(%{public}s), dev = %{public}s", errno, strerror(errno), fileName);
71 return;
72 }
73 g_fd = fileno(fd);
74 if (g_fd < 0) {
75 return;
76 }
77 RME_LOGI("rtg Open success");
78 return;
79 }
80
BasicCloseRtgNode()81 __attribute__((destructor)) void BasicCloseRtgNode()
82 {
83 if (g_fd < 0) {
84 return;
85 }
86 FILE* fd = fdopen(g_fd, "r+");
87 if (fd != nullptr) {
88 RME_LOGI("rtg Close g_fd ret is %{public}d", g_fd);
89 fclose(fd);
90 }
91 g_fd = -1;
92 }
93
EnableRtg(bool flag)94 int EnableRtg(bool flag)
95 {
96 int ret = 0;
97 struct rtg_enable_data enableData;
98 char configStr[] = "load_freq_switch:1;sched_cycle:1";
99 enableData.enable = flag;
100 enableData.len = sizeof(configStr);
101 enableData.data = configStr;
102 if (g_fd < 0) {
103 return g_fd;
104 }
105 ret = ioctl(g_fd, CMD_ID_SET_ENABLE, &enableData);
106 if (ret != 0) {
107 RME_LOGE("set rtg config to [%{public}d] failed, ret = %{public}d, errno = %{public}d (%{public}s)",
108 flag,
109 ret,
110 errno,
111 strerror(errno));
112 } else {
113 RME_LOGI("set rtg config to [%{public}d] success.", flag);
114 }
115 return 0;
116 };
117
AddThreadToRtg(int tid,int grpId,int prioType,bool isBlue)118 int AddThreadToRtg(int tid, int grpId, int prioType, [[maybe_unused]] bool isBlue)
119 {
120 if (g_fd < 0) {
121 return g_fd;
122 }
123 struct rtg_grp_data grp_data;
124 int ret;
125 (void)memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
126 grp_data.tid_num = 1;
127 grp_data.tids[0] = tid;
128 grp_data.grp_id = grpId;
129 grp_data.rtg_cmd = CMD_ADD_RTG_THREAD;
130 grp_data.prio_type = prioType;
131 ret = ioctl(g_fd, CMD_ID_SET_RTG, &grp_data);
132 if (ret != 0) {
133 RME_LOGE("add thread to rtg failed, grpId = %{public}d, ret = %{public}d, errno = %{public}d (%{public}s)",
134 grpId,
135 ret,
136 errno,
137 strerror(errno));
138 } else {
139 RME_LOGI("add thread to rtg success");
140 }
141 return ret;
142 }
143
AddThreadsToRtg(vector<int> tids,int grpId,int prioType,bool isBlue)144 int AddThreadsToRtg(vector<int> tids, int grpId, int prioType, [[maybe_unused]] bool isBlue)
145 {
146 struct rtg_grp_data grp_data;
147 int ret;
148 if (g_fd < 0) {
149 return g_fd;
150 }
151 (void)memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
152 int num = static_cast<int>(tids.size());
153 if (num > MAX_TID_NUM) {
154 return -1;
155 }
156 grp_data.tid_num = num;
157 grp_data.grp_id = grpId;
158 grp_data.rtg_cmd = CMD_ADD_RTG_THREAD;
159 grp_data.prio_type = prioType;
160 for (int i = 0; i < num; i++) {
161 if (tids[i] < 0) {
162 return -1;
163 }
164 grp_data.tids[i] = tids[i];
165 }
166 ret = ioctl(g_fd, CMD_ID_SET_RTG, &grp_data);
167 if (ret == 0) {
168 RME_LOGI("add rtg grp success");
169 } else {
170 RME_LOGE("add thread to rtg failed, grpId = %{public}d, ret = %{public}d, errno = %{public}d (%{public}s)",
171 grpId,
172 ret,
173 errno,
174 strerror(errno));
175 }
176 return ret;
177 };
178
RemoveRtgThread(int tid,bool isBlue)179 int RemoveRtgThread(int tid, [[maybe_unused]] bool isBlue)
180 {
181 if (g_fd < 0) {
182 return g_fd;
183 }
184 struct rtg_grp_data grp_data;
185 int ret;
186 (void)memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
187 grp_data.tid_num = 1;
188 grp_data.tids[0] = tid;
189 grp_data.rtg_cmd = CMD_REMOVE_RTG_THREAD;
190 ret = ioctl(g_fd, CMD_ID_SET_RTG, &grp_data);
191 if (ret != 0) {
192 RME_LOGE("remove grp failed, ret = %{public}d, errno = %{public}d (%{public}s)", ret, errno, strerror(errno));
193 } else {
194 RME_LOGI("remove grp success.");
195 }
196 return ret;
197 };
198
RemoveRtgThreads(vector<int> tids,bool isBlue)199 int RemoveRtgThreads(vector<int> tids, [[maybe_unused]] bool isBlue)
200 {
201 struct rtg_grp_data grp_data;
202 int ret;
203 if (g_fd < 0) {
204 return g_fd;
205 }
206 (void)memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
207 int num = static_cast<int>(tids.size());
208 if (num > MAX_TID_NUM) {
209 return -1;
210 }
211 grp_data.tid_num = num;
212 grp_data.rtg_cmd = CMD_REMOVE_RTG_THREAD;
213 for (int i = 0; i < num; i++) {
214 if (tids[i] < 0) {
215 return -1;
216 }
217 grp_data.tids[i] = tids[i];
218 }
219 ret = ioctl(g_fd, CMD_ID_SET_RTG, &grp_data);
220 if (ret < 0) {
221 RME_LOGE("remove grp threads failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
222 } else {
223 RME_LOGI("remove grp threads success, get rtg id %{public}d.", ret);
224 }
225 return ret;
226 }
227
DestroyRtgGrp(int grpId)228 int DestroyRtgGrp(int grpId)
229 {
230 if (g_fd < 0) {
231 return g_fd;
232 }
233 struct rtg_grp_data grp_data;
234 int ret;
235 (void)memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
236 grp_data.rtg_cmd = CMD_DESTROY_RTG_GRP;
237 grp_data.grp_id = grpId;
238 ret = ioctl(g_fd, CMD_ID_SET_RTG, &grp_data);
239 if (ret != 0) {
240 RME_LOGE("destroy rtg grp failed, grpId = %{public}d, ret = %{public}d, errno = %{public}d (%{public}s)",
241 grpId,
242 ret,
243 errno,
244 strerror(errno));
245 } else {
246 RME_LOGI("destroy rtg grp success, get rtg id:%{public}d, ret:%{public}d.", grpId, ret);
247 }
248 return ret;
249 };
250
SetFrameRateAndPrioType(int rtgId,int rate,int rtgType)251 int SetFrameRateAndPrioType(int rtgId, int rate, int rtgType)
252 {
253 if (g_fd < 0) {
254 return g_fd;
255 }
256 int ret = 0;
257 char str_data[MAX_LENGTH] = {};
258 (void)sprintf_s(str_data, sizeof(str_data), "rtgId:%d;rate:%d;type:%d", rtgId, rate, rtgType);
259 struct rtg_str_data strData;
260 strData.len = strlen(str_data);
261 strData.data = str_data;
262
263 ret = ioctl(g_fd, CMD_ID_SET_RTG_ATTR, &strData);
264 if (ret != 0) {
265 RME_LOGE("set rtg attr failed (rtgId:%{public}d;rate:%{public}d;type:%{public}d), ret = %{public}d, errno = "
266 "%{public}d (%{public}s)",
267 rtgId,
268 rate,
269 rtgType,
270 ret,
271 errno,
272 strerror(errno));
273 } else {
274 RME_LOGD("set rtg attr success.");
275 }
276 return ret;
277 }
278
BeginFrameFreq(int stateParam)279 int BeginFrameFreq(int stateParam)
280 {
281 if (g_fd < 0) {
282 return g_fd;
283 }
284 int ret = 0;
285 struct proc_state_data state_data;
286 state_data.state_param = stateParam;
287
288 ret = ioctl(g_fd, CMD_ID_BEGIN_FRAME_FREQ, &state_data);
289 return ret;
290 }
291
EndFrameFreq(int stateParam)292 int EndFrameFreq(int stateParam)
293 {
294 if (g_fd < 0) {
295 return g_fd;
296 }
297 int ret = 0;
298 struct proc_state_data state_data;
299 state_data.state_param = stateParam;
300
301 ret = ioctl(g_fd, CMD_ID_END_FRAME_FREQ, &state_data);
302 return ret;
303 }
304
EndScene(int grpId)305 int EndScene(int grpId)
306 {
307 int ret = 0;
308 if (g_fd < 0) {
309 RME_LOGE("Open fail /proc/self/sched_rtg_ctrl");
310 return g_fd;
311 }
312 struct proc_state_data state_data;
313 state_data.grp_id = grpId;
314
315 ret = ioctl(g_fd, CMD_ID_END_SCENE, &state_data);
316 if (ret == 0) {
317 RME_LOGI("set EndScene success.");
318 }
319 return ret;
320 }
321
SetMinUtil(int stateParam)322 int SetMinUtil(int stateParam)
323 {
324 int ret = 0;
325 struct proc_state_data state_data;
326 state_data.state_param = stateParam;
327
328 if (g_fd < 0) {
329 return g_fd;
330 }
331 ret = ioctl(g_fd, CMD_ID_SET_MIN_UTIL, &state_data);
332 if (ret != 0) {
333 RME_LOGE("set min util failed, ret = %{public}d, errno = %{public}d (%{public}s)", ret, errno, strerror(errno));
334 } else {
335 RME_LOGI("set min util success, get ret %{public}d.", ret);
336 }
337 return ret;
338 }
339
SetMaxUtil(int grpId,int stateParam)340 int SetMaxUtil(int grpId, int stateParam)
341 {
342 return 0;
343 }
344
SetMargin(int stateParam)345 int SetMargin(int stateParam)
346 {
347 int ret = 0;
348 struct proc_state_data state_data;
349 state_data.state_param = stateParam;
350
351 if (g_fd < 0) {
352 return g_fd;
353 }
354 ret = ioctl(g_fd, CMD_ID_SET_MARGIN, &state_data);
355 return ret;
356 }
357
SearchRtgForTid(int tid)358 int SearchRtgForTid(int tid)
359 {
360 if (g_fd < 0) {
361 return g_fd;
362 }
363 if (tid <= 0) {
364 RME_LOGI("Search tid err: invalid tid.");
365 return -1;
366 }
367 int ret = 0;
368 struct proc_state_data search_data;
369 (void)memset_s(&search_data, sizeof(struct proc_state_data), 0, sizeof(struct proc_state_data));
370 search_data.state_param = tid;
371 ret = ioctl(g_fd, CMD_ID_SEARCH_RTG, &search_data);
372 if (ret >= 0) {
373 RME_LOGD("Search tid %{public}d success with rtg_grp %{public}d", tid, ret);
374 }
375 return ret;
376 }
377
GetRtgEnable()378 int GetRtgEnable()
379 {
380 if (g_fd < 0) {
381 return g_fd;
382 }
383 int ret = 0;
384 struct rtg_enable_data enableData;
385 ret = ioctl(g_fd, CMD_ID_GET_ENABLE, &enableData);
386 if (ret < 0) {
387 RME_LOGE(
388 "get rtg enable failed, ret = %{public}d, errno = %{public}d (%{public}s)", ret, errno, strerror(errno));
389 }
390 return ret;
391 }
392
GetAppExpelAbility(const std::string & appBundleName)393 bool GetAppExpelAbility(const std::string &appBundleName)
394 {
395 return false;
396 }
397 } // namespace RME
398 } // namespace OHOS
399