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