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 31namespace OHOS { 32namespace RME { 33namespace { 34constexpr size_t MAX_LENGTH = 100; 35} 36 37const char RTG_SCHED_IPC_MAGIC = 0xAB; 38static 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 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 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 87int 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 111int 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 137int 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 172int 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 192int 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 221int 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 244int 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 272int 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 285int 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 298int 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 315int 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 333int SetMaxUtil(int grpId, int stateParam) 334{ 335 return 0; 336} 337 338int 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 351int 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 371int 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 386bool GetAppExpelAbility(const std::string &appBundleName) 387{ 388 return false; 389} 390} // namespace RME 391} // namespace OHOS 392