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