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 "intellisense_server.h"
17 #include <fcntl.h>
18 #include <hitrace_meter.h>
19 #include <list>
20 #include <map>
21 #include <new>
22 #include <set>
23 #include <securec.h>
24 #include <string>
25 #include <sys/ioctl.h>
26 #include <unistd.h>
27 #include <vector>
28 #include "qos_common.h"
29 #include "para_config.h"
30 #include "rtg_interface.h"
31 #include "rme_log_domain.h"
32
33 #undef LOG_TAG
34 #define LOG_TAG "ueaServer-IntelliSenseServer"
35
36 namespace OHOS {
37 namespace RME {
38 namespace {
39 static std::string configFilePath = "/system/etc/frame_aware_sched/hwrme.xml"; // need To check the exact file path.
40 constexpr int WEB_BASE_UID = 1000001;
41 constexpr int WEB_END_UID = 1099999;
42 const char RTG_SCHED_IPC_MAGIC = 0xAB;
43 constexpr int RTG_TYPE_MAX = 3;
44 }
45 using namespace std;
46 using namespace QosCommon;
47
48 IMPLEMENT_SINGLE_INSTANCE(IntelliSenseServer);
49
50 #define CMD_ID_SET_RTG \
51 _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG, struct rtg_str_data)
52
Init()53 void IntelliSenseServer::Init()
54 {
55 if (!ReadXml()) {
56 RME_LOGI("[Init]: readXml failed!");
57 return;
58 }
59 m_switch = std::stoi(m_generalPara["enable"]);
60 if (!m_switch) {
61 RME_LOGI("[Init]:xml switch close!");
62 return;
63 }
64 int ret = EnableRtg(true);
65 if (ret < 0) {
66 RME_LOGE("[Init]: enable rtg failed!");
67 return;
68 }
69 m_unsupportApp = {
70 "com.ohos.launcher",
71 "com.ohos.systemui",
72 "com.ohos.screenlock",
73 "com.ohos.wallpaper"
74 };
75 RME_LOGI("[Init]:Init rtg and readXml finish!");
76 }
77
ReadXml()78 bool IntelliSenseServer::ReadXml()
79 {
80 if (!m_needReadXml) {
81 return false;
82 }
83 m_needReadXml = false;
84 if (ParaConfig::IsXmlPrepared(configFilePath)) {
85 m_generalPara = ParaConfig::GetGeneralConfig();
86 m_subEventPara = ParaConfig::GetSubEventConfig();
87 m_fpsList = ParaConfig::GetFpsList();
88 m_renderTypeList = ParaConfig::GetRenderTypeList();
89 if (!m_generalPara.empty() && !m_subEventPara.empty() && !m_fpsList.empty() && !m_renderTypeList.empty()) {
90 m_readXmlSuc = true;
91 RME_LOGI("[ReadXml]: read slide scene xml success!");
92 return true;
93 }
94 }
95 RME_LOGE("[ReadXml]: read slide scene xml not success!");
96 return false;
97 }
98
NewForeground(int pid,int uid)99 void IntelliSenseServer::NewForeground(int pid, int uid)
100 {
101 HITRACE_METER(HITRACE_TAG_ACE);
102 int newCreatedRtg = 0;
103 for (auto iter = m_historyApp.begin(); iter != m_historyApp.end(); iter++) {
104 if (iter->GetAppUid() == uid) {
105 RME_LOGI("[ReportMessage]pid %{public}d change to foreground.", pid);
106 if (iter->GetAppState() != AppState::APP_FOREGROUND) {
107 iter->SetUiTid(pid);
108 newCreatedRtg = TryCreateRtgForApp(&*iter);
109 }
110 if (newCreatedRtg) {
111 iter->SetAppState(AppState::APP_FOREGROUND);
112 } else {
113 iter->SetAppState(AppState::APP_FOREGROUND_WITHOUT_RTG);
114 }
115 break;
116 }
117 }
118 }
119
TryCreateRtgForApp(AppInfo * app)120 int IntelliSenseServer::TryCreateRtgForApp(AppInfo *app)
121 {
122 if (!app) {
123 RME_LOGE("[TryCreateRtg]: null app!");
124 return 0;
125 }
126 int grpId = CreateNewRtgGrp(RT_PRIO, RT_NUM);
127 if (grpId <= 0) {
128 RME_LOGE("[TryCreateRtg]: createNewRtgGroup failed! grpId:%{public}d", grpId);
129 app->SetRtgrp(0);
130 return grpId;
131 }
132 app->SetRtgrp(grpId);
133 int uiTid = app->GetUiTid();
134 int renderTid = app->GetRenderTid();
135 if (uiTid > 0) {
136 AddThreadToRtg(uiTid, grpId, 0); // add ui thread
137 }
138 if (renderTid > 0) {
139 AddThreadToRtg(renderTid, grpId, 0); // add render thread
140 }
141 return grpId;
142 }
143
NewBackground(int pid)144 void IntelliSenseServer::NewBackground(int pid)
145 {
146 HITRACE_METER(HITRACE_TAG_ACE);
147 RME_LOGI("[ReportMessage]pid %{public}d change to background.", pid);
148 for (auto iter = m_historyApp.begin(); iter != m_historyApp.end(); iter++) {
149 if (iter->GetAppPid() != pid) {
150 continue;
151 }
152 iter->SetAppState(AppState::APP_BACKGROUND);
153 int grpId = iter->GetRtgrp();
154 if (grpId > 0) {
155 EndScene(grpId);
156 DestroyRtgGrp(grpId);
157 }
158 }
159 }
160
NewAppRecord(int pid,int uid)161 void IntelliSenseServer::NewAppRecord(int pid, int uid)
162 {
163 for (auto iter = m_historyApp.begin(); iter != m_historyApp.end(); iter++) {
164 if (iter->GetAppUid() == uid) {
165 RME_LOGI("[NewAppRecord]pid %{public}d already exist.", pid);
166 return;
167 }
168 }
169 AppInfo tempRecord(pid, uid);
170 tempRecord.SetAppState(AppState::APP_FOREGROUND_WITHOUT_RTG);
171 m_historyApp.push_back(tempRecord);
172 }
173
NewDiedProcess(int pid)174 void IntelliSenseServer::NewDiedProcess(int pid)
175 {
176 HITRACE_METER(HITRACE_TAG_ACE);
177 RME_LOGI("[ReportMessage]pid %{public}d died.", pid);
178 for (auto iter = m_historyApp.begin(); iter != m_historyApp.end();) {
179 if (iter->GetAppPid() == pid) {
180 int grpId = iter->GetRtgrp();
181 if (grpId > 0) {
182 EndScene(grpId);
183 DestroyRtgGrp(grpId);
184 }
185 iter = m_historyApp.erase(iter);
186 } else {
187 iter++;
188 }
189 }
190 }
191
GetRecordOfPid(int pid)192 std::list<AppInfo>::iterator IntelliSenseServer::GetRecordOfPid(int pid)
193 {
194 for (auto iter = m_historyApp.begin(); iter != m_historyApp.end(); iter++) {
195 if (iter->GetAppPid() == pid) {
196 return iter;
197 }
198 }
199 return m_historyApp.end();
200 }
201
ReportRenderThread(const int pid,const int uid,int renderTid)202 void IntelliSenseServer::ReportRenderThread(const int pid, const int uid, int renderTid)
203 {
204 if (uid >= WEB_BASE_UID && uid <= WEB_END_UID) {
205 return;
206 }
207 if (!m_switch) {
208 return;
209 }
210 HITRACE_METER(HITRACE_TAG_ACE);
211 auto record = GetRecordOfPid(pid);
212 if (record == m_historyApp.end()) {
213 RME_LOGE("Didn't find render in history app %{public}d with render %{public}d", pid, renderTid);
214 return;
215 }
216 record->SetRenderTid(renderTid);
217 int grpId = record->GetRtgrp();
218 if (grpId >= 0 && record->GetAppState() == AppState::APP_FOREGROUND) {
219 int ret = AddThreadToRtg(renderTid, grpId, 0); // add render thread
220 RME_LOGE("web test ReportRenderThread uid is %{public}d", uid);
221 if (ret != 0) {
222 RME_LOGE("[OnFore]:add render thread fail! pid:%{public}d,rtg:%{public}d!ret:%{publid}d",
223 renderTid, grpId, ret);
224 }
225 }
226 }
227
ReportContinuousTask(const int pid,const int uid,const int status)228 void IntelliSenseServer::ReportContinuousTask(const int pid, const int uid, const int status)
229 {
230 if (!m_switch) {
231 return;
232 }
233 HITRACE_METER(HITRACE_TAG_ACE);
234 switch (status) {
235 case static_cast<int>(ContinuousTaskState::TASK_START):
236 RME_LOGI("[ReportContinuousTask]:%{public}d continuous task start", pid);
237 break;
238 case static_cast<int>(ContinuousTaskState::TASK_END):
239 RME_LOGI("[ReportContinuousTask]:%{public}d continuous task end", pid);
240 break;
241 default:
242 RME_LOGI("[ReportContinuousTask]:unknown continuous task status!");
243 break;
244 }
245 }
246
ReportWindowFocus(const int pid,const int uid,int isFocus)247 void IntelliSenseServer::ReportWindowFocus(const int pid, const int uid, int isFocus)
248 {
249 if (!m_switch) {
250 return;
251 }
252 HITRACE_METER(HITRACE_TAG_ACE);
253 switch (isFocus) {
254 case static_cast<int>(WindowState::FOCUS_YES): // isFocus: 0
255 RME_LOGI("[ReportWindowFocus]:%{public}d get focus", pid);
256 break;
257 case static_cast<int>(WindowState::FOCUS_NO): // isFocus: 1
258 RME_LOGI("[ReportWindowFocus]:%{public}d lost focus", pid);
259 break;
260 default:
261 RME_LOGI("[ReportWindowFocus]:unknown msg!");
262 break;
263 }
264 }
265
CheckCgroupState(CgroupPolicy cgroup)266 inline CgroupPolicy IntelliSenseServer::CheckCgroupState(CgroupPolicy cgroup)
267 {
268 return ((cgroup == CgroupPolicy::SP_FOREGROUND) || (cgroup == CgroupPolicy::SP_TOP_APP)) ?
269 CgroupPolicy::SP_FOREGROUND : CgroupPolicy::SP_BACKGROUND;
270 }
271
ReportCgroupChange(const int pid,const int uid,const int oldGroup,const int newGroup)272 void IntelliSenseServer::ReportCgroupChange(const int pid, const int uid, const int oldGroup, const int newGroup)
273 {
274 if (uid >= WEB_BASE_UID && uid <= WEB_END_UID) {
275 return;
276 }
277 if (!m_switch) {
278 return;
279 }
280 HITRACE_METER(HITRACE_TAG_ACE);
281 CgroupPolicy oldState = CheckCgroupState(static_cast<CgroupPolicy>(oldGroup));
282 CgroupPolicy newState = CheckCgroupState(static_cast<CgroupPolicy>(newGroup));
283 if (oldState == newState) {
284 return;
285 }
286 if (newState == CgroupPolicy::SP_BACKGROUND) {
287 RME_LOGI("CgroupChange NewBackground");
288 NewBackground(pid);
289 AuthBackground(pid);
290 } else if (newState == CgroupPolicy::SP_FOREGROUND) {
291 RME_LOGI("web test CgroupChange NewForeground uid is %{public}d", uid);
292 NewForeground(pid, uid);
293 AuthForeground(pid);
294 }
295 }
296
ReportAppInfo(const int pid,const int uid,const std::string bundleName,ThreadState state)297 void IntelliSenseServer::ReportAppInfo(const int pid, const int uid, const std::string bundleName, ThreadState state)
298 {
299 if (!m_switch) {
300 return;
301 }
302 if (state == ThreadState::CREATE) {
303 AuthForeground(pid);
304 }
305 RME_LOGI("Get app info:%{public}d %{public}d %{public}s %{public}d",
306 pid, uid, bundleName.c_str(), static_cast<int>(state));
307 }
308
ReportProcessInfo(const int pid,const int uid,const std::string bundleName,ThreadState state)309 void IntelliSenseServer::ReportProcessInfo(const int pid,
310 const int uid, const std::string bundleName, ThreadState state)
311 {
312 if (uid >= WEB_BASE_UID && uid <= WEB_END_UID) {
313 return;
314 }
315 if (!m_switch) {
316 return;
317 }
318 HITRACE_METER(HITRACE_TAG_ACE);
319 if (m_unsupportApp.find(bundleName) != m_unsupportApp.end()) {
320 return;
321 }
322 switch (state) {
323 case ThreadState::DIED:
324 RME_LOGI("ProcessInfo NewDiedProcess");
325 AuthAppKilled(pid);
326 NewDiedProcess(pid);
327 break;
328 case ThreadState::CREATE:
329 RME_LOGI("ProcessInfo NewAppRecord");
330 NewAppRecord(pid, uid);
331 break;
332 default:
333 RME_LOGD("unknown state : %{public}d", static_cast<int>(state));
334 break;
335 }
336 return;
337 }
338
SetPara(const int32_t currentFps,const int32_t currentRenderType)339 void IntelliSenseServer::SetPara(const int32_t currentFps, const int32_t currentRenderType)
340 {
341 if (!m_switch) {
342 return;
343 }
344 RME_LOGI("[SetPara]:ioctl SetPara!\n");
345 std::string key = std::to_string(currentRenderType) + " " + std::to_string(currentFps);
346 map<std::string, int> tempMap = m_subEventPara[key];
347 RME_LOGI("[SetPara]:subEventPara map size: %{public}zu", tempMap.size());
348 }
349
AuthAppKilled(int pid)350 void IntelliSenseServer::AuthAppKilled(int pid)
351 {
352 int ret = AuthDelete(pid);
353 if (ret == 0) {
354 RME_LOGI("auth_delete %{public}d success", pid);
355 } else {
356 RME_LOGE("auth_delete %{public}d failed", pid);
357 }
358 }
359
AuthForeground(int pid)360 void IntelliSenseServer::AuthForeground(int pid)
361 {
362 unsigned int flag = AF_RTG_ALL;
363 int status = AUTH_STATUS_FOREGROUND;
364 int ret = AuthEnable(pid, flag, status);
365 if (ret == 0) {
366 RME_LOGI("auth_enable %{public}d success", pid);
367 } else {
368 RME_LOGE("auth_enable %{public}d failed", pid);
369 }
370 }
371
AuthBackground(int pid)372 void IntelliSenseServer::AuthBackground(int pid)
373 {
374 int ret = AuthPause(pid);
375 if (ret == 0) {
376 RME_LOGI("auth_pause %{public}d success", pid);
377 } else {
378 RME_LOGE("auth_pause %{public}d failed", pid);
379 }
380 }
381
CreateNewRtgGrp(int prioType,int rtNum)382 int IntelliSenseServer::CreateNewRtgGrp(int prioType, int rtNum)
383 {
384 struct rtg_grp_data grp_data;
385 int ret;
386 char fileName[] = "/proc/self/sched_rtg_ctrl";
387 int fd = open(fileName, O_RDWR);
388 if (fd < 0) {
389 RME_LOGE("Open file /proc/self/sched_rth_ctrl, errno = %{public}d", errno);
390 return fd;
391 }
392 (void)memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
393 if ((prioType > 0) && (prioType < RTG_TYPE_MAX)) {
394 grp_data.prio_type = prioType;
395 }
396 if (rtNum > 0) {
397 grp_data.rt_cnt = rtNum;
398 }
399 grp_data.rtg_cmd = CMD_CREATE_RTG_GRP;
400 ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data);
401 if (ret < 0) {
402 RME_LOGE("create rtg grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
403 } else {
404 RME_LOGI("create rtg grp success, get rtg id %{public}d.", ret);
405 }
406 close(fd);
407 return ret;
408 }
409 } // namespace RME
410 } // namesapce OHOS
411