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