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