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