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