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