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 <fcntl.h>
17 #include <securec.h>
18 #include <sys/ioctl.h>
19 #include <sys/resource.h>
20 #include <unistd.h>
21 #include <hitrace_meter.h>
22 #include <linux/sched.h>
23 #include "accesstoken_kit.h"
24 #include "concurrent_task_log.h"
25 #include "rtg_interface.h"
26 #include "ipc_skeleton.h"
27 #include "parameters.h"
28 #include "concurrent_task_controller.h"
29 
30 using namespace OHOS::RME;
31 using namespace OHOS::Security::AccessToken;
32 
33 namespace OHOS {
34 namespace ConcurrentTask {
35 namespace {
36     const std::string INTERVAL_DDL = "persist.ffrt.interval.renderthread";
37     const std::string INTERVAL_APP_RATE = "persist.ffrt.interval.appRate";
38     const std::string INTERVAL_RS_RATE = "persist.ffrt.interval.rsRate";
39     const std::string CONFIG_FILE_NAME = "etc/qos_manager/qos_manager_config.xml";
40     constexpr int CURRENT_RATE = 120;
41     constexpr int PARAM_TYPE = 1;
42     constexpr int UNI_APP_RATE_ID = -1;
43     const char RTG_SCHED_IPC_MAGIC = 0xAB;
44     constexpr int RTG_TYPE_MAX = 3;
45     constexpr int RS_UID = 1003;
46     constexpr int EXECUTOR_LIMIT_NUM = 3;
47     constexpr int APP_TYPE_VIDEO = 10067;
48     constexpr int APP_TYPE_VIDEO_CLIP = 10026;
49     constexpr int APP_TYPE_INVALID = -1;
50 }
51 
52 #define CMD_ID_SET_RTG \
53     _IOWR(RTG_SCHED_IPC_MAGIC, SET_RTG, struct rtg_str_data)
54 
GetInstance()55 TaskController& TaskController::GetInstance()
56 {
57     static TaskController instance;
58     return instance;
59 }
60 
RequestAuth(const Json::Value & payload)61 void TaskController::RequestAuth(const Json::Value& payload)
62 {
63     {
64         std::lock_guard<std::mutex> autolock(configReaderMutex_);
65         if (!configEnable_ && !ConfigReaderInit()) {
66             return;
67         }
68     }
69     pid_t uid = IPCSkeleton::GetInstance().GetCallingUid();
70     auto bundleName = GetProcessNameByToken();
71     if (configReader_->IsBundleNameAuth(bundleName) || configReader_->IsUidAuth(uid)) {
72         pid_t pid = IPCSkeleton::GetInstance().GetCallingPid();
73         AuthSystemProcess(pid);
74         return;
75     }
76     CONCUR_LOGE("Invalid uid %{public}d, can't call RequestAuth", uid);
77 }
78 
ReportData(uint32_t resType,int64_t value,const Json::Value & payload)79 void TaskController::ReportData(uint32_t resType, int64_t value, const Json::Value& payload)
80 {
81     pid_t uid = IPCSkeleton::GetInstance().GetCallingUid();
82     if (GetProcessNameByToken() != RESOURCE_SCHEDULE_PROCESS_NAME) {
83         CONCUR_LOGE("Invalid uid %{public}d, only RSS can call ReportData", uid);
84         return;
85     }
86     if (!CheckJsonValid(payload)) {
87         return;
88     }
89     std::string strRequstType = "";
90     try {
91         strRequstType = payload["type"].asString();
92     } catch (...) {
93         CONCUR_LOGE("Unexpected type format");
94         return;
95     }
96     if (strRequstType.length() == 0) {
97         CONCUR_LOGE("Get payload type err");
98         return;
99     }
100     int requstType = GetRequestType(strRequstType);
101     DealSystemRequest(requstType, payload);
102     PrintInfo();
103 }
104 
QueryInterval(int queryItem,IntervalReply & queryRs)105 void TaskController::QueryInterval(int queryItem, IntervalReply& queryRs)
106 {
107     pid_t uid = IPCSkeleton::GetInstance().GetCallingUid();
108     pid_t pid = IPCSkeleton::GetInstance().GetCallingPid();
109     switch (queryItem) {
110         case QUERY_UI:
111             QueryUi(uid, queryRs);
112             break;
113         case QUERY_RENDER:
114             QueryRender(uid, queryRs);
115             break;
116         case QUERY_RENDER_SERVICE:
117             QueryRenderService(uid, queryRs);
118             break;
119         case QUERY_RENDER_SERVICE_MAIN:
120             QueryRenderServiceMain(uid, pid, queryRs);
121             break;
122         case QUERY_RENDER_SERVICE_RENDER:
123             QueryRenderServiceRender(uid, pid, queryRs);
124             break;
125         case QUERY_COMPOSER:
126             QueryHwc(uid, queryRs);
127             break;
128         case QUERY_HARDWARE:
129             QueryHardware(uid, pid, queryRs);
130             break;
131         case QUERY_EXECUTOR_START:
132             QueryExecutorStart(uid, pid, queryRs);
133             break;
134         default:
135             break;
136     }
137 }
138 
GetProcessNameByToken()139 std::string TaskController::GetProcessNameByToken()
140 {
141     AccessTokenID tokenID = IPCSkeleton::GetInstance().GetCallingTokenID();
142     NativeTokenInfo tokenInfo;
143     if (AccessTokenKit::GetNativeTokenInfo(tokenID, tokenInfo) != AccessTokenKitRet::RET_SUCCESS) {
144         return "";
145     }
146     return tokenInfo.processName;
147 }
148 
QueryUi(int uid,IntervalReply & queryRs)149 void TaskController::QueryUi(int uid, IntervalReply& queryRs)
150 {
151     pid_t pid = IPCSkeleton::GetInstance().GetCallingPid();
152     auto iter = GetRecordOfPid(pid);
153     if (iter == foregroundApp_.end()) {
154         CONCUR_LOGD("Query ui with pid %{public}d failed", pid);
155         return;
156     }
157     int grpId = iter->GetGrpId();
158     if (grpId <= 0) {
159         CONCUR_LOGI("%{public}d Query ui with none grpid", pid);
160         queryRs.rtgId = -1;
161     } else {
162         queryRs.rtgId = grpId;
163     }
164     queryRs.bundleName = appBundleName[pid];
165 }
166 
QueryRender(int uid,IntervalReply & queryRs)167 void TaskController::QueryRender(int uid, IntervalReply& queryRs)
168 {
169     pid_t pid = IPCSkeleton::GetInstance().GetCallingPid();
170     auto iter = GetRecordOfPid(pid);
171     if (iter == foregroundApp_.end()) {
172         CONCUR_LOGD("Query render with pid %{public}d failed", pid);
173         return;
174     }
175     int grpId = iter->GetGrpId();
176     if (grpId <= 0) {
177         CONCUR_LOGI("%{public}d Query render with none grpid", pid);
178         queryRs.rtgId = -1;
179     } else {
180         queryRs.rtgId = grpId;
181     }
182 }
183 
QueryRenderService(int uid,IntervalReply & queryRs)184 void TaskController::QueryRenderService(int uid, IntervalReply& queryRs)
185 {
186     if (uid != RS_UID) {
187         return;
188     }
189     int queryTid = queryRs.tid;
190     if (renderServiceMainGrpId_ <= 0) {
191         TryCreateRSMainGrp();
192         CONCUR_LOGI("uid %{public}d query rs group failed and create %{public}d.", uid, renderServiceMainGrpId_);
193         if (renderServiceMainGrpId_ <= 0) {
194             CONCUR_LOGE("uid %{public}d create rs group failed", uid);
195             return;
196         }
197     }
198 
199     queryRs.rtgId = renderServiceMainGrpId_;
200     if (queryTid <= 0) {
201         return;
202     }
203     list<int>::iterator iter = find(rsThreads_.begin(), rsThreads_.end(), queryTid);
204     if (iter != rsThreads_.end()) {
205         return;
206     }
207     queryRs.rtgId = renderServiceMainGrpId_;
208     int ret = AddThreadToRtg(queryTid, renderServiceMainGrpId_, PRIO_RT);
209     if (ret < 0) {
210         CONCUR_LOGE("uid %{public}d tid %{public}d join rs group failed", uid, queryTid);
211         return;
212     }
213     CONCUR_LOGI("uid %{public}d tid %{public}d join rs group success in Query", uid, queryTid);
214     SetFrameRateAndPrioType(renderServiceMainGrpId_, CURRENT_RATE, PARAM_TYPE);
215 }
216 
QueryRenderServiceMain(int uid,int pid,IntervalReply & queryRs)217 void TaskController::QueryRenderServiceMain(int uid, int pid, IntervalReply& queryRs)
218 {
219     if (uid != RS_UID) {
220         return;
221     }
222     if (authedRSPid_ != pid) {
223         if (AuthSystemProcess(pid) != 0) {
224             return;
225         }
226         authedRSPid_ = pid;
227     }
228     if (renderServiceMainGrpId_ <= 0) {
229         TryCreateRSMainGrp();
230         CONCUR_LOGI("uid %{public}d query rs group failed and create %{public}d.", uid, renderServiceMainGrpId_);
231         if (renderServiceMainGrpId_ <= 0) {
232             CONCUR_LOGE("uid %{public}d create rs group failed", uid);
233             return;
234         }
235     }
236     queryRs.rtgId = renderServiceMainGrpId_;
237     if (renderServiceMainTid_ <= 0) {
238         renderServiceMainTid_ = queryRs.tid;
239         int ret = AddThreadToRtg(renderServiceMainTid_, renderServiceMainGrpId_, PRIO_RT);
240         if (ret < 0) {
241             CONCUR_LOGE("uid %{public}d tid %{public}d join rs group failed.", uid, renderServiceMainTid_);
242         }
243     }
244     SetFrameRateAndPrioType(renderServiceMainGrpId_, CURRENT_RATE, PARAM_TYPE);
245 }
246 
QueryRenderServiceRender(int uid,int pid,IntervalReply & queryRs)247 void TaskController::QueryRenderServiceRender(int uid, int pid, IntervalReply& queryRs)
248 {
249     if (uid != RS_UID) {
250         return;
251     }
252     if (renderServiceRenderGrpId_ <= 0) {
253         TryCreateRSRenderGrp();
254         if (renderServiceRenderGrpId_ <= 0) {
255             CONCUR_LOGE("uid %{public}d create rs group failed", uid);
256             return;
257         }
258     }
259     queryRs.rtgId = renderServiceRenderGrpId_;
260     if (renderServiceRenderTid_ <= 0 || renderServiceRenderTid_ != queryRs.tid) {
261         renderServiceRenderTid_ = queryRs.tid;
262         int ret = AddThreadToRtg(renderServiceRenderTid_, renderServiceRenderGrpId_, PRIO_RT);
263         if (ret < 0) {
264             CONCUR_LOGE("uid %{public}d tid %{public}d join rs group failed.", uid, renderServiceMainGrpId_);
265         }
266     }
267     SetFrameRateAndPrioType(renderServiceRenderGrpId_, CURRENT_RATE, PARAM_TYPE);
268 }
269 
QueryHardware(int uid,int pid,IntervalReply & queryRs)270 void TaskController::QueryHardware(int uid, int pid, IntervalReply& queryRs)
271 {
272     if (uid != RS_UID) {
273         return;
274     }
275     if (hardwareGrpId_ < 0) {
276         return;
277     }
278     hardwareTid_ = queryRs.tid;
279     TryCreateRSMainGrp();
280     int ret = AddThreadToRtg(hardwareTid_, renderServiceMainGrpId_, PRIO_RT);
281     if (ret < 0) {
282         CONCUR_LOGE("uid %{public}d tid %{public}d join hardware group failed.", uid, hardwareTid_);
283         return;
284     }
285     queryRs.rtgId = hardwareGrpId_;
286 }
287 
QueryExecutorStart(int uid,int pid,IntervalReply & queryRs)288 void TaskController::QueryExecutorStart(int uid, int pid, IntervalReply& queryRs)
289 {
290     if (uid != RS_UID) {
291         return;
292     }
293     if (renderServiceMainGrpId_ < 0) {
294         return;
295     }
296     std::lock_guard<std::mutex> lock(executorStartLock_);
297     if (executorNum_ >= EXECUTOR_LIMIT_NUM) {
298         return;
299     }
300     if (queryRs.tid <= 0) {
301         return;
302     }
303     int ret = AddThreadToRtg(queryRs.tid, renderServiceMainGrpId_, PRIO_RT);
304     if (ret < 0) {
305         CONCUR_LOGE("uid %{public}d tid %{public}d join executor group failed.", uid, renderServiceMainTid_);
306         return;
307     }
308     executorNum_++;
309     queryRs.rtgId = renderServiceMainGrpId_;
310 }
311 
QueryHwc(int uid,IntervalReply & queryRs)312 void TaskController::QueryHwc(int uid, IntervalReply& queryRs)
313 {
314     pid_t pid = IPCSkeleton::GetInstance().GetCallingPid();
315     auto iter = GetRecordOfPid(pid);
316     if (iter == foregroundApp_.end()) {
317         CONCUR_LOGD("Query ipc thread with pid %{public}d failed", pid);
318         return;
319     }
320     int grpId = iter->GetGrpId();
321     if (grpId <= 0) {
322         CONCUR_LOGI("%{public}d Query ipc thread with none grpid", pid);
323         queryRs.rtgId = -1;
324     } else {
325         queryRs.rtgId = grpId;
326     }
327 }
328 
Init()329 void TaskController::Init()
330 {
331     TypeMapInit();
332     qosPolicy_.Init();
333     TryCreateRsGroup();
334 
335     std::lock_guard<std::mutex> autolock(configReaderMutex_);
336     if (!configEnable_) {
337         ConfigReaderInit();
338     }
339 }
340 
ConfigReaderInit()341 bool TaskController::ConfigReaderInit()
342 {
343     configReader_ = make_unique<ConfigReader>();
344     if (!configReader_) {
345         CONCUR_LOGE("configReader_ initialize error!");
346         return configEnable_;
347     }
348 
349     std::string realPath;
350     configReader_->GetRealConfigPath(CONFIG_FILE_NAME.c_str(), realPath);
351     if (realPath.empty() || !configReader_->LoadFromConfigFile(realPath)) {
352         CONCUR_LOGE("config load failed!");
353         return configEnable_;
354     }
355     configEnable_ = true;
356     ddlSceneSchedSwitch_ = configReader_->GetPowerModeSchedSwitch();
357     CONCUR_LOGI("deadline scene sched switch = %{public}d", ddlSceneSchedSwitch_);
358     return configEnable_;
359 }
360 
Release()361 void TaskController::Release()
362 {
363     msgType_.clear();
364     appTypeCache_.clear();
365     if (renderServiceMainGrpId_ > 0) {
366         DestroyRtgGrp(renderServiceMainGrpId_);
367         renderServiceMainGrpId_ = -1;
368     }
369     if (renderServiceRenderGrpId_ > 0) {
370         DestroyRtgGrp(renderServiceRenderGrpId_);
371         renderServiceRenderGrpId_ = -1;
372     }
373     ddlSceneSchedSwitch_ = false;
374 
375     std::lock_guard<std::mutex> autolock(configReaderMutex_);
376     configReader_ = nullptr;
377 }
378 
TypeMapInit()379 void TaskController::TypeMapInit()
380 {
381     msgType_.clear();
382     msgType_.insert(pair<std::string, int>("foreground", MSG_FOREGROUND));
383     msgType_.insert(pair<std::string, int>("background", MSG_BACKGROUND));
384     msgType_.insert(pair<std::string, int>("appStart", MSG_APP_START));
385     msgType_.insert(pair<std::string, int>("appKilled", MSG_APP_KILLED));
386     msgType_.insert(pair<std::string, int>("continuousStart", MSG_CONTINUOUS_TASK_START));
387     msgType_.insert(pair<std::string, int>("continuousEnd", MSG_CONTINUOUS_TASK_END));
388     msgType_.insert(pair<std::string, int>("getFocus", MSG_GET_FOCUS));
389     msgType_.insert(pair<std::string, int>("loseFocus", MSG_LOSE_FOCUS));
390     msgType_.insert(pair<std::string, int>("enterInteractionScene", MSG_ENTER_INTERACTION_SCENE));
391     msgType_.insert(pair<std::string, int>("exitInteractionScene", MSG_EXIT_INTERACTION_SCENE));
392 }
393 
TryCreateRSMainGrp()394 void TaskController::TryCreateRSMainGrp()
395 {
396     if (renderServiceMainGrpId_ == -1) {
397         renderServiceMainGrpId_ = TryCreateSystemGroup();
398         hardwareGrpId_ = renderServiceMainGrpId_;
399     }
400 }
401 
TryCreateRSRenderGrp()402 void TaskController::TryCreateRSRenderGrp()
403 {
404     if (renderServiceRenderGrpId_ == -1) {
405         renderServiceRenderGrpId_ = TryCreateSystemGroup();
406     }
407 }
408 
TryCreateRsGroup()409 void TaskController::TryCreateRsGroup()
410 {
411     TryCreateRSMainGrp();
412     TryCreateRSRenderGrp();
413 }
414 
TryCreateSystemGroup()415 int TaskController::TryCreateSystemGroup()
416 {
417     if (!rtgEnabled_) {
418         rtgEnabled_ = EnableRtg(true) < 0 ? false : true;
419         if (!rtgEnabled_) {
420             CONCUR_LOGE("Rtg enable failed");
421             return -1;
422         }
423         CONCUR_LOGI("Enable Rtg");
424     }
425     int grpId = CreateNewRtgGrp(PRIO_RT, MAX_KEY_THREADS);
426     if (grpId <= 0) {
427         CONCUR_LOGI("CreateRsRtgGroup with RT failed, try change to normal type.");
428         grpId = CreateNewRtgGrp(PRIO_NORMAL, MAX_KEY_THREADS);
429     }
430     if (grpId <= 0) {
431         CONCUR_LOGI("CreateRsRtgGroup failed! rtGrp:%{public}d", grpId);
432         return -1;
433     }
434     return grpId;
435 }
436 
GetRequestType(std::string strRequstType)437 int TaskController::GetRequestType(std::string strRequstType)
438 {
439     auto iter = msgType_.find(strRequstType);
440     if (iter == msgType_.end()) {
441         return MSG_TYPE_MAX;
442     }
443     return msgType_[strRequstType];
444 }
445 
ParsePayload(const Json::Value & payload,int & uid,int & pid,std::string & bundleName)446 bool TaskController::ParsePayload(const Json::Value& payload, int& uid, int& pid, std::string& bundleName)
447 {
448     try {
449         uid = stoi(payload["uid"].asString());
450         pid = stoi(payload["pid"].asString());
451         bundleName = payload["bundleName"].asString();
452     } catch(...) {
453         CONCUR_LOGE("Unexpected uid or pid format");
454         return false;
455     }
456     if (uid > 0 && pid > 0) {
457         return true;
458     }
459     return false;
460 }
461 
DealSystemRequest(int requestType,const Json::Value & payload)462 void TaskController::DealSystemRequest(int requestType, const Json::Value& payload)
463 {
464     int uid = -1;
465     int pid = -1;
466     std::string bundleName = "";
467     if (!ParsePayload(payload, uid, pid, bundleName)) {
468         return;
469     }
470     switch (requestType) {
471         case MSG_FOREGROUND:
472             NewForeground(uid, pid);
473             break;
474         case MSG_BACKGROUND:
475             NewBackground(uid, pid);
476             break;
477         case MSG_APP_START:
478             NewAppStart(uid, pid, bundleName, ParseAppType(payload));
479             break;
480         case MSG_APP_KILLED:
481             AppKilled(uid, pid);
482             break;
483         case MSG_CONTINUOUS_TASK_START:
484         case MSG_CONTINUOUS_TASK_END:
485             ContinuousTaskProcess(uid, pid, requestType);
486             break;
487         case MSG_GET_FOCUS:
488         case MSG_LOSE_FOCUS:
489             FocusStatusProcess(uid, pid, requestType);
490             break;
491         case MSG_ENTER_INTERACTION_SCENE:
492         case MSG_EXIT_INTERACTION_SCENE:
493             InteractionSceneProcess(requestType);
494             break;
495         default:
496             CONCUR_LOGE("Unknown system request");
497             break;
498     }
499 }
500 
GetRecordOfPid(int pid)501 std::list<ForegroundAppRecord>::iterator TaskController::GetRecordOfPid(int pid)
502 {
503     std::lock_guard<std::mutex> lock(appInfoLock_);
504     for (auto iter = foregroundApp_.begin(); iter != foregroundApp_.end(); iter++) {
505         if (iter->GetPid() == pid) {
506             return iter;
507         }
508     }
509     return foregroundApp_.end();
510 }
511 
NewForeground(int uid,int pid)512 void TaskController::NewForeground(int uid, int pid)
513 {
514     int uiTid = pid;
515     auto it = find(authApps_.begin(), authApps_.end(), pid);
516     if (it == authApps_.end()) {
517         CONCUR_LOGI("un-authed pid %{public}d", pid);
518         return;
519     }
520     int ret = AuthGet(pid);
521     if (ret != static_cast<int>(AuthStatus::AUTH_STATUS_FOCUS)) {
522         unsigned int pidParam = static_cast<unsigned int>(pid);
523         unsigned int uaFlag = AF_RTG_ALL;
524         unsigned int status = static_cast<unsigned int>(AuthStatus::AUTH_STATUS_FOREGROUND);
525         int ret = AuthEnable(pidParam, uaFlag, status);
526         if (ret == 0) {
527             CONCUR_LOGI("auth_enable %{public}d success", pid);
528         } else {
529             CONCUR_LOGE("auth_enable %{public}d fail with ret %{public}d", pid, ret);
530         }
531         CONCUR_LOGI("pid %{public}d change to foreground.", pid);
532     } else {
533         CONCUR_LOGI("pid %{public}d is already focus", pid);
534     }
535     bool found = false;
536     bool ddlEnabled = OHOS::system::GetBoolParameter(INTERVAL_DDL, false);
537     std::lock_guard<std::mutex> lock(appInfoLock_);
538     for (auto iter = foregroundApp_.begin(); iter != foregroundApp_.end(); iter++) {
539         if (iter->GetPid() == pid) {
540             found = true;
541             if (ddlEnabled && pid != curGamePid_) {
542                 iter->AddKeyThread(uiTid, PRIO_RT);
543             }
544             iter->BeginScene();
545         }
546     }
547     if (!found) {
548         NewForegroundAppRecord(pid, uiTid, ddlEnabled);
549     }
550 }
551 
NewForegroundAppRecord(int pid,int uiTid,bool ddlEnabled)552 void TaskController::NewForegroundAppRecord(int pid, int uiTid, bool ddlEnabled)
553 {
554     auto appRecord = foregroundApp_.emplace_back(pid, uiTid, pid != curGamePid_);
555     if (foregroundApp_.size() <= 0 || appRecord.GetPid() != pid) {
556         CONCUR_LOGE("pid %{public}d create app record failed", pid);
557         return;
558     }
559     if (appRecord.IsValid()) {
560         if (ddlEnabled && pid != curGamePid_) {
561             appRecord.AddKeyThread(uiTid, PRIO_RT);
562         }
563         appRecord.BeginScene();
564     }
565 }
566 
NewBackground(int uid,int pid)567 void TaskController::NewBackground(int uid, int pid)
568 {
569     auto it = find(authApps_.begin(), authApps_.end(), pid);
570     if (it == authApps_.end()) {
571         CONCUR_LOGI("un-authed pid %{public}d", pid);
572         return;
573     }
574     CONCUR_LOGI("pid %{public}d change to background.", pid);
575     unsigned int pidParam = static_cast<unsigned int>(pid);
576 
577     int ret = AuthPause(pidParam);
578     if (ret == 0) {
579         CONCUR_LOGI("auth_pause %{public}d success", pid);
580     } else {
581         CONCUR_LOGI("auth_pause %{public}d fail with %{public}d", pid, ret);
582     }
583     std::lock_guard<std::mutex> lock(appInfoLock_);
584     for (auto iter = foregroundApp_.begin(); iter != foregroundApp_.end(); iter++) {
585         if (iter->GetPid() == pid) {
586             iter->EndScene();
587             return;
588         }
589     }
590 }
591 
NewAppStart(int uid,int pid,const std::string & bundleName,int appType)592 void TaskController::NewAppStart(int uid, int pid, const std::string& bundleName, int appType)
593 {
594     CONCUR_LOGI("pid %{public}d start.", pid);
595     unsigned int pidParam = static_cast<unsigned int>(pid);
596     unsigned int uaFlag = AF_RTG_ALL;
597     unsigned int status = static_cast<unsigned int>(AuthStatus::AUTH_STATUS_DEFAULT);
598 
599     int ret = AuthEnable(pidParam, uaFlag, status);
600     if (ret == 0) {
601         CONCUR_LOGI("auth_enable %{public}d success", pid);
602     } else {
603         CONCUR_LOGE("auth_enable %{public}d fail with ret %{public}d", pid, ret);
604         return;
605     }
606     std::lock_guard<std::mutex> lock(appInfoLock_);
607     authApps_.push_back(pid);
608     appBundleName[pid] = bundleName;
609     if (ddlSceneSchedSwitch_ && appType != APP_TYPE_INVALID) {
610         appTypeCache_[bundleName] = appType;
611     }
612 }
613 
AppKilled(int uid,int pid)614 void TaskController::AppKilled(int uid, int pid)
615 {
616     CONCUR_LOGI("pid %{public}d killed.", pid);
617     unsigned int pidParam = static_cast<unsigned int>(pid);
618     int ret = AuthDelete(pidParam);
619     if (ret == 0) {
620         CONCUR_LOGI("auth_delete %{public}d success", pid);
621     } else {
622         CONCUR_LOGE("auth_delete %{public}d fail with %{public}d", pid, ret);
623     }
624     std::lock_guard<std::mutex> lock(appInfoLock_);
625     for (auto iter = foregroundApp_.begin(); iter != foregroundApp_.end(); iter++) {
626         if (iter->GetPid() == pid) {
627             foregroundApp_.erase(iter++);
628             break;
629         }
630     }
631     for (auto iter = authApps_.begin(); iter != authApps_.end(); iter++) {
632         if (*iter == pid) {
633             authApps_.erase(iter);
634             break;
635         }
636     }
637     appBundleName.erase(pid);
638 }
639 
AuthSystemProcess(int pid)640 int TaskController::AuthSystemProcess(int pid)
641 {
642     unsigned int uaFlag = AF_RTG_ALL;
643     unsigned int status = static_cast<unsigned int>(AuthStatus::AUTH_STATUS_SYSTEM_SERVER);
644     int ret = AuthEnable(pid, uaFlag, status);
645     if (ret == 0) {
646         CONCUR_LOGI("auth process %{public}d success", pid);
647     } else {
648         CONCUR_LOGI("auth process %{public}d failed, ret %{public}d", pid, ret);
649     }
650     return ret;
651 }
652 
ContinuousTaskProcess(int uid,int pid,int status)653 void TaskController::ContinuousTaskProcess(int uid, int pid, int status)
654 {
655     int ret = -1;
656     if (status == static_cast<int>(MSG_CONTINUOUS_TASK_START)) {
657         ret = AuthEnhance(pid, true);
658         CONCUR_LOGI("auth_enhance pid %{public}d start, ret %{public}d", pid, ret);
659     } else if (status == static_cast<int>(MSG_CONTINUOUS_TASK_END)) {
660         ret = AuthEnhance(pid, false);
661         CONCUR_LOGI("auth_enhance pid %{public}d end, ret %{public}d", pid, ret);
662     } else {
663         CONCUR_LOGE("Invalid auth_enhance status %{public}d", status);
664     }
665 }
666 
FocusStatusProcess(int uid,int pid,int status)667 void TaskController::FocusStatusProcess(int uid, int pid, int status)
668 {
669     int ret = -1;
670     unsigned int rtgFlag = AF_RTG_ALL;
671     unsigned int qosFlag = AF_QOS_DELEGATED;
672     if (status == static_cast<int>(MSG_GET_FOCUS)) {
673         ret = AuthSwitch(pid, rtgFlag, qosFlag, static_cast<unsigned int>(AuthStatus::AUTH_STATUS_FOCUS));
674         CONCUR_LOGI("pid %{public}d get focus. ret %{public}d", pid, ret);
675         if (ddlSceneSchedSwitch_) {
676             if (IsVideoApp(pid)) {
677                 isVideoApp_ = true;
678                 CONCUR_LOGD("video app bundleName %{public}s get focus", appBundleName[pid].c_str());
679             } else {
680                 isVideoApp_ = false;
681             }
682         }
683     } else if (status == static_cast<int>(MSG_LOSE_FOCUS)) {
684         ret = AuthSwitch(pid, rtgFlag, qosFlag, static_cast<unsigned int>(AuthStatus::AUTH_STATUS_FOREGROUND));
685         CONCUR_LOGI("pid %{public}d lose focus. ret %{public}d", pid, ret);
686         isVideoApp_ = false;
687     } else {
688         CONCUR_LOGE("Invalid focus status %{public}d", status);
689     }
690 }
691 
InteractionSceneProcess(int status)692 void TaskController::InteractionSceneProcess(int status)
693 {
694     std::lock_guard<std::mutex> lock(ddlPowerModeLock_);
695     if (ddlSceneSchedSwitch_) {
696         if (status ==  MSG_ENTER_INTERACTION_SCENE) {
697             DeadlinePerfMode();
698         } else if (status == MSG_EXIT_INTERACTION_SCENE) {
699             if (isVideoApp_) {
700                 return;
701             }
702             DeadlinePowerMode();
703         }
704     }
705 }
706 
DeadlinePerfMode()707 void TaskController::DeadlinePerfMode()
708 {
709     if (ddlPowerModeEnable_) {
710         StartTrace(HITRACE_TAG_ACE, "Deadline perf mode");
711         SetAppAndRenderServicRate(uniAppRate_, systemRate_);
712         ddlPowerModeEnable_ = false;
713         CONCUR_LOGI("Deadline switch to perf mode");
714         FinishTrace(HITRACE_TAG_ACE);
715     }
716 }
717 
DeadlinePowerMode()718 void TaskController::DeadlinePowerMode()
719 {
720     if (!ddlPowerModeEnable_) {
721         StartTrace(HITRACE_TAG_ACE, "Deadline power mode");
722         int appRate = uniAppRate_;
723         int rsRate = systemRate_;
724         if (configReader_) {
725             appRate = configReader_->GetDegratationFps(appRate);
726             rsRate = configReader_->GetDegratationFps(rsRate);
727         }
728         SetAppAndRenderServicRate(appRate, rsRate);
729         ddlPowerModeEnable_ = true;
730         CONCUR_LOGI("Deadline switch to power mode");
731         FinishTrace(HITRACE_TAG_ACE);
732     }
733 }
QueryDeadline(int queryItem,DeadlineReply & ddlReply,const Json::Value & payload)734 void TaskController::QueryDeadline(int queryItem, DeadlineReply& ddlReply, const Json::Value& payload)
735 {
736     pid_t uid = IPCSkeleton::GetInstance().GetCallingUid();
737     std::string processName = GetProcessNameByToken();
738     if (processName != RENDER_SERVICE_PROCESS_NAME && processName != GAME_ACCELERATE_SCHED_PROCESS_NAME) {
739         CONCUR_LOGE("Invalid uid %{public}d, only RS or RSS can call QueryDeadline", uid);
740         return;
741     }
742     switch (queryItem) {
743         case DDL_RATE: {
744             ModifySystemRate(payload);
745             break;
746         }
747         case MSG_GAME: {
748             ModifyGameState(payload);
749             break;
750         }
751         default: {
752             break;
753         }
754     }
755 }
756 
ModifyGameState(const Json::Value & payload)757 void TaskController::ModifyGameState(const Json::Value& payload)
758 {
759     if (!CheckJsonValid(payload)) {
760         CONCUR_LOGE("[MSG_GAME]receive json invalid");
761         return;
762     }
763     if (payload["gameMsg"].isNull()) {
764         CONCUR_LOGE("[MSG_GAME]message is null");
765         return;
766     }
767     std::string gameMsg = payload["gameMsg"].asString();
768     int oldGamePid = curGamePid_;
769     int newGamePid = GetGamePid(gameMsg);
770     curGamePid_ = newGamePid;
771     CONCUR_LOGI("[MSG_GAME]current game pid is %{public}d, old game pid is %{public}d",
772                 newGamePid, oldGamePid);
773     if (curGamePid_ == -1) {
774         return;
775     }
776     std::lock_guard<std::mutex> lock(appInfoLock_);
777     for (auto iter = foregroundApp_.begin(); iter != foregroundApp_.end(); iter++) {
778         if (iter->GetPid() == curGamePid_ && iter->GetGrpId() >= 0) {
779             CONCUR_LOGI("[MSG_GAME]destroy rtg grp, pid is %{public}d grpId is %{public}d",
780                         iter->GetPid(), iter->GetGrpId());
781             DestroyRtgGrp(iter->GetGrpId());
782             iter->SetGrpId(-1);
783             break;
784         }
785     }
786     return;
787 }
788 
GetGamePid(const std::string & gameMsg) const789 int TaskController::GetGamePid(const std::string &gameMsg) const
790 {
791     GameStatus status = GetGameScene(gameMsg);
792     CONCUR_LOGI("[MSG_GAME]gamescene status %{public}d", status);
793     int gamePid = -1;
794     if (status == GAME_ENTRY_MSG) {
795         size_t pos = gameMsg.find(",");
796         if (pos == string::npos) {
797             return -1;
798         }
799         int ret = sscanf_s(gameMsg.substr(0, pos).c_str(), "{\"gamePid\":\"%d\"", &gamePid);
800         if (ret == -1) {
801             CONCUR_LOGE("[MSG_GAME]message parsing failed, ret is %{public}d", ret);
802         } else {
803             CONCUR_LOGI("[MSG_GAME]message parsing success");
804         }
805     }
806     return gamePid;
807 }
808 
GetGameScene(const std::string & gameMsg) const809 GameStatus TaskController::GetGameScene(const std::string &gameMsg) const
810 {
811     if (gameMsg.find("gameScene\":\"1") != std::string::npos) {
812         return GAME_ENTRY_MSG;
813     }
814     if (gameMsg.find("gameScene\":\"0") != std::string::npos) {
815         return GAME_EXIT_MSG;
816     }
817     if (gameMsg.find("cameraScene\":\"1") != std::string::npos) {
818         return CAMERA_ENTRY_MSG;
819     }
820     if (gameMsg.find("cameraScene\":\"0") != std::string::npos) {
821         return CAMERA_EXIT_MSG;
822     }
823     if (gameMsg.find("GTXGamePid\":") != std::string::npos) {
824         return GAME_GTX_MSG;
825     }
826     return STATUS_MSG_MAX;
827 }
828 
ModifySystemRate(const Json::Value & payload)829 bool TaskController::ModifySystemRate(const Json::Value& payload)
830 {
831     if (!CheckJsonValid(payload)) {
832         CONCUR_LOGI("service receive json invalid");
833         return false;
834     }
835     SetAppRate(payload);
836     SetRenderServiceRate(payload);
837     return true;
838 }
839 
SetAppRate(const Json::Value & payload)840 void TaskController::SetAppRate(const Json::Value& payload)
841 {
842     int rtgId = 0;
843     int uiTid = 0;
844     int appRate = FindRateFromInfo(UNI_APP_RATE_ID, payload);
845     if (appRate > 0 && appRate != uniAppRate_) {
846         CONCUR_LOGD("set unified app rate %{public}d", appRate);
847         uniAppRate_ = appRate;
848         if (ddlSceneSchedSwitch_ && ddlPowerModeEnable_ && configReader_) {
849             appRate = configReader_->GetDegratationFps(appRate);
850         }
851         bool ret = OHOS::system::SetParameter(INTERVAL_APP_RATE, std::to_string(appRate));
852         if (ret == false) {
853             CONCUR_LOGI("set app rate param failed");
854         }
855         StartTrace(HITRACE_TAG_ACE,
856             "SetAppRate:" + std::to_string(appRate) + " ret:" + std::to_string(ret));
857         FinishTrace(HITRACE_TAG_ACE);
858         return;
859     }
860     std::lock_guard<std::mutex> lock(appInfoLock_);
861     for (auto iter = foregroundApp_.begin(); iter != foregroundApp_.end(); iter++) {
862         uiTid = iter->GetUiTid();
863         rtgId = iter->GetGrpId();
864         if (uiTid <= 0 || rtgId <= 0) {
865             continue;
866         }
867         appRate = FindRateFromInfo(uiTid, payload);
868         if (appRate > 0 && appRate != iter->GetRate()) {
869             CONCUR_LOGI("set app rate %{public}d rtgId is %{public}d, old rate is %{public}d",
870                         appRate, rtgId, iter->GetRate());
871             SetFrameRate(rtgId, appRate);
872             iter->SetRate(appRate);
873         }
874     }
875     return;
876 }
877 
FindRateFromInfo(int uiTid,const Json::Value & payload)878 int TaskController::FindRateFromInfo(int uiTid, const Json::Value& payload)
879 {
880     int appRate = 0;
881     if (payload[std::to_string(uiTid)].isNull()) {
882         CONCUR_LOGI("FindRateFromInfo tid %{public}d is null", uiTid);
883         return appRate;
884     }
885     try {
886         appRate = stoi(payload[std::to_string(uiTid)].asString());
887     } catch (...) {
888         CONCUR_LOGI("application %{public}d is not in rtg_group", uiTid);
889     }
890     return appRate;
891 }
892 
SetRenderServiceRate(const Json::Value & payload)893 void TaskController::SetRenderServiceRate(const Json::Value& payload)
894 {
895     int rsRate = FindRateFromInfo(renderServiceMainTid_, payload);
896     std::lock_guard<std::mutex> lock(rateInfoLock_);
897     if (renderServiceMainGrpId_ > 0 && rsRate > 0 && rsRate != systemRate_) {
898         CONCUR_LOGD("set rs rate %{public}d rtgId is %{public}d, old rate is %{public}d",
899                     rsRate, renderServiceMainGrpId_, systemRate_);
900         SetFrameRate(renderServiceMainGrpId_, rsRate);
901         systemRate_ = rsRate;
902         if (ddlSceneSchedSwitch_ && ddlPowerModeEnable_ && configReader_) {
903             rsRate = configReader_->GetDegratationFps(rsRate);
904         }
905         bool ret = OHOS::system::SetParameter(INTERVAL_RS_RATE, std::to_string(rsRate));
906         if (ret == false) {
907             CONCUR_LOGI("set rs rate param failed");
908         }
909         StartTrace(HITRACE_TAG_ACE,
910             "SetRSRate:" + std::to_string(rsRate) + " ret:" + std::to_string(ret));
911         FinishTrace(HITRACE_TAG_ACE);
912     }
913 }
914 
SetAppAndRenderServicRate(int appRate,int rsRate)915 void TaskController::SetAppAndRenderServicRate(int appRate, int rsRate)
916 {
917     bool ret = OHOS::system::SetParameter(INTERVAL_APP_RATE, std::to_string(appRate));
918     if (ret == false) {
919         CONCUR_LOGI("set app rate param failed");
920     }
921     StartTrace(HITRACE_TAG_ACE,
922         "SetAppRate:" + std::to_string(appRate) + " ret:" + std::to_string(ret));
923     FinishTrace(HITRACE_TAG_ACE);
924 
925     ret = OHOS::system::SetParameter(INTERVAL_RS_RATE, std::to_string(rsRate));
926     if (ret == false) {
927         CONCUR_LOGI("set rs rate param failed");
928     }
929     StartTrace(HITRACE_TAG_ACE,
930         "SetRSRate:" + std::to_string(rsRate) + " ret:" + std::to_string(ret));
931     FinishTrace(HITRACE_TAG_ACE);
932 }
933 
CheckJsonValid(const Json::Value & payload)934 bool TaskController::CheckJsonValid(const Json::Value& payload)
935 {
936     Json::ValueType type = payload.type();
937     if (type != Json::objectValue) {
938         CONCUR_LOGE("error payload");
939         return false;
940     }
941     if (payload.empty()) {
942         CONCUR_LOGI("payload empty");
943         return false;
944     }
945     return true;
946 }
947 
SetFrameRate(int rtgId,int rate)948 void TaskController::SetFrameRate(int rtgId, int rate)
949 {
950     if (rtgId > 0) {
951         SetFrameRateAndPrioType(rtgId, rate, PARAM_TYPE);
952     }
953 }
954 
PrintInfo()955 void TaskController::PrintInfo()
956 {
957     std::lock_guard<std::mutex> lock(appInfoLock_);
958     for (auto iter = foregroundApp_.begin(); iter != foregroundApp_.end(); iter++) {
959         iter->PrintKeyThreads();
960     }
961 }
962 
CreateNewRtgGrp(int prioType,int rtNum)963 int TaskController::CreateNewRtgGrp(int prioType, int rtNum)
964 {
965     struct rtg_grp_data grp_data;
966     int ret;
967     char fileName[] = "/proc/self/sched_rtg_ctrl";
968     int fd = open(fileName, O_RDWR);
969     if (fd < 0) {
970         CONCUR_LOGE("Open file /proc/self/sched_rth_ctrl, errno = %{public}d", errno);
971         return fd;
972     }
973     (void)memset_s(&grp_data, sizeof(struct rtg_grp_data), 0, sizeof(struct rtg_grp_data));
974     if ((prioType > 0) && (prioType < RTG_TYPE_MAX)) {
975         grp_data.prio_type = prioType;
976     }
977     if (rtNum > 0) {
978         grp_data.rt_cnt = rtNum;
979     }
980     grp_data.rtg_cmd = CMD_CREATE_RTG_GRP;
981     ret = ioctl(fd, CMD_ID_SET_RTG, &grp_data);
982     if (ret < 0) {
983         CONCUR_LOGE("create rtg grp failed, errno = %{public}d (%{public}s)", errno, strerror(errno));
984     } else {
985         CONCUR_LOGI("create rtg grp success, get rtg id %{public}d.", ret);
986     }
987     close(fd);
988     return ret;
989 }
990 
ParseAppType(const Json::Value & payload)991 int TaskController::ParseAppType(const Json::Value& payload)
992 {
993     int appType = APP_TYPE_INVALID;
994     if (payload.isMember("appType") && payload["appType"].isString()) {
995         try {
996             appType = stoi(payload["appType"].asString());
997         } catch (...) {
998             CONCUR_LOGE("Unexpected apptype format");
999             return APP_TYPE_INVALID;
1000         }
1001     }
1002     return appType;
1003 }
1004 
IsVideoApp(int pid)1005 bool TaskController::IsVideoApp(int pid)
1006 {
1007     if (!ddlSceneSchedSwitch_ || appBundleName.find(pid) == appBundleName.end()) {
1008         return false;
1009     }
1010     std::string bundleName = appBundleName[pid];
1011     if (appTypeCache_.find(bundleName) != appTypeCache_.end()) {
1012         return appTypeCache_[bundleName] == APP_TYPE_VIDEO ||
1013             appTypeCache_[bundleName]== APP_TYPE_VIDEO_CLIP;
1014     }
1015     return false;
1016 }
1017 
ForegroundAppRecord(int pid,int uiTid,bool createGrp)1018 ForegroundAppRecord::ForegroundAppRecord(int pid, int uiTid, bool createGrp)
1019 {
1020     pid_ = pid;
1021     uiTid_ = uiTid;
1022     if (OHOS::system::GetBoolParameter(INTERVAL_DDL, false) && createGrp) {
1023         grpId_ = TaskController::GetInstance().CreateNewRtgGrp(PRIO_RT, MAX_KEY_THREADS);
1024     } else {
1025         grpId_ = -1;
1026     }
1027 }
1028 
~ForegroundAppRecord()1029 ForegroundAppRecord::~ForegroundAppRecord()
1030 {
1031     if (grpId_ > 0) {
1032         DestroyRtgGrp(grpId_);
1033     }
1034 }
1035 
AddKeyThread(int tid,int prio)1036 void ForegroundAppRecord::AddKeyThread(int tid, int prio)
1037 {
1038     int rtgPrio = (prio >= PRIO_NORMAL) ? PRIO_NORMAL : PRIO_RT;
1039     if (keyThreads_.find(tid) != keyThreads_.end()) {
1040         return;
1041     }
1042     if (grpId_ <= 0) {
1043         CONCUR_LOGI("Add key thread fail: Grp id not been created success, tid is %{public}d", tid);
1044         return;
1045     }
1046     if (keyThreads_.size() >= MAX_KEY_THREADS) {
1047         CONCUR_LOGI("Add key thread fail: Key threads num limit.");
1048         return;
1049     }
1050     if (prio == RPIO_IN) {
1051         setpriority(PRIO_PROCESS, tid, -13); // -13 represent spcial nice in qos
1052     } else {
1053         int ret = AddThreadToRtg(tid, grpId_, rtgPrio);
1054         if (ret != 0) {
1055             CONCUR_LOGI("Add key thread fail: Kernel err report. ret is %{public}d", ret);
1056         } else {
1057             CONCUR_LOGI("Add key thread %{public}d", tid);
1058         }
1059         keyThreads_.insert(tid);
1060     }
1061 }
1062 
BeginScene()1063 bool ForegroundAppRecord::BeginScene()
1064 {
1065     if (grpId_ <= 0) {
1066         CONCUR_LOGI("Error begin scene in pid %{public}d", pid_);
1067         return false;
1068     }
1069     OHOS::RME::BeginFrameFreq(0);
1070     OHOS::RME::EndFrameFreq(0);
1071     return true;
1072 }
1073 
EndScene()1074 bool ForegroundAppRecord::EndScene()
1075 {
1076     if (grpId_ <= 0) {
1077         CONCUR_LOGI("Error end scene loss grpId_ in pid %{public}d", pid_);
1078         return false;
1079     }
1080     OHOS::RME::EndScene(grpId_);
1081     return true;
1082 }
1083 
GetPid() const1084 int ForegroundAppRecord::GetPid() const
1085 {
1086     return pid_;
1087 }
1088 
GetGrpId() const1089 int ForegroundAppRecord::GetGrpId() const
1090 {
1091     return grpId_;
1092 }
1093 
SetGrpId(int grpId)1094 void ForegroundAppRecord::SetGrpId(int grpId)
1095 {
1096     grpId_ = grpId;
1097 }
1098 
SetRate(int appRate)1099 void ForegroundAppRecord::SetRate(int appRate)
1100 {
1101     rate_ = appRate;
1102 }
1103 
GetRate() const1104 int ForegroundAppRecord::GetRate() const
1105 {
1106     return rate_;
1107 }
1108 
SetUiTid(int uiTid)1109 void ForegroundAppRecord::SetUiTid(int uiTid)
1110 {
1111     uiTid_ = uiTid;
1112 }
1113 
GetUiTid() const1114 int ForegroundAppRecord::GetUiTid() const
1115 {
1116     return uiTid_;
1117 }
1118 
IsValid()1119 bool ForegroundAppRecord::IsValid()
1120 {
1121     if (pid_ > 0) {
1122         return true;
1123     }
1124     return false;
1125 }
1126 
PrintKeyThreads()1127 void ForegroundAppRecord::PrintKeyThreads()
1128 {
1129     std::string strLog = "pid ";
1130     strLog.append(std::to_string(pid_));
1131     strLog.append(" has key threads: ");
1132     for (auto iter = keyThreads_.begin(); iter != keyThreads_.end(); iter++) {
1133         std::string temp = std::to_string(*iter);
1134         strLog.append(temp);
1135         strLog.append(", ");
1136     }
1137     CONCUR_LOGD("%{public}s", strLog.c_str());
1138 }
1139 } // namespace ConcurrentTask
1140 } // namespace OHOS
1141