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