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