1 /*
2  * Copyright (c) 2023 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 "audio_schedule.h"
17 #include "audio_schedule_guard.h"
18 
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <cstring>
22 #include <unordered_map>
23 #include <set>
24 
25 #ifdef RESSCHE_ENABLE
26 #include "res_type.h"
27 #include "res_sched_client.h"
28 #endif
29 
30 #include "audio_utils.h"
31 #include "audio_common_log.h"
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 using namespace OHOS::AudioStandard;
38 
39 #ifdef RESSCHE_ENABLE
40 const uint32_t AUDIO_QOS_LEVEL = 7;
41 const int32_t DEFAULT_QOS_LEVEL = -1;
42 const uint32_t REPORTDATA_TIMEOUT = 8;
43 static std::mutex g_rssMutex;
44 static std::set<uint32_t> g_tidToReport = {};
45 constexpr uint32_t g_type = OHOS::ResourceSchedule::ResType::RES_TYPE_THREAD_QOS_CHANGE;
46 constexpr int64_t g_value = 0;
47 
ConfigPayload(uint32_t pid,uint32_t tid,const char * bundleName,int32_t qosLevel,std::unordered_map<std::string,std::string> & mapPayload)48 void ConfigPayload(uint32_t pid, uint32_t tid, const char *bundleName, int32_t qosLevel,
49     std::unordered_map<std::string, std::string> &mapPayload)
50 {
51     std::string strBundleName = bundleName;
52     std::string strPid = std::to_string(pid);
53     std::string strTid = std::to_string(tid);
54     std::string strQos = std::to_string(qosLevel);
55     mapPayload["pid"] = strPid;
56     mapPayload[strTid] = strQos;
57     mapPayload["bundleName"] = strBundleName;
58 }
59 
ScheduleReportData(uint32_t pid,uint32_t tid,const char * bundleName)60 void ScheduleReportData(uint32_t pid, uint32_t tid, const char *bundleName)
61 {
62     AudioXCollie audioXcollie("RSS::ReportData with qos level 7, pid " + std::to_string(pid) +
63         ", tid " + std::to_string(tid), REPORTDATA_TIMEOUT);
64     Trace trace ("Rss::ReportData with qos level 7");
65     AUDIO_INFO_LOG("Report tid %{public}u", tid);
66     std::unordered_map<std::string, std::string> mapPayload;
67     ConfigPayload(pid, tid, bundleName, AUDIO_QOS_LEVEL, mapPayload);
68     OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(g_type, g_value, mapPayload);
69 }
70 
UnscheduleReportData(uint32_t pid,uint32_t tid,const char * bundleName)71 void UnscheduleReportData(uint32_t pid, uint32_t tid, const char* bundleName)
72 {
73     AudioXCollie audioXcollie("RSS::ReportData with qos level -1, pid " + std::to_string(pid) +
74         ", tid " + std::to_string(tid), REPORTDATA_TIMEOUT);
75     Trace trace ("Rss::ReportData with qos level -1");
76     std::unordered_map<std::string, std::string> mapPayload;
77     ConfigPayload(pid, tid, bundleName, DEFAULT_QOS_LEVEL, mapPayload);
78     OHOS::ResourceSchedule::ResSchedClient::GetInstance().ReportData(g_type, g_value, mapPayload);
79 }
80 
UnscheduleThreadInServer(uint32_t pid,uint32_t tid)81 void UnscheduleThreadInServer(uint32_t pid, uint32_t tid)
82 {
83     std::lock_guard<std::mutex> lock(g_rssMutex);
84     if (g_tidToReport.find(tid) != g_tidToReport.end()) {
85         AUDIO_INFO_LOG("Remove tid in server %{public}u", tid);
86         g_tidToReport.erase(tid);
87     }
88     UnscheduleReportData(pid, tid, "audio_server");
89 }
90 
ScheduleThreadInServer(uint32_t pid,uint32_t tid)91 void ScheduleThreadInServer(uint32_t pid, uint32_t tid)
92 {
93     std::lock_guard<std::mutex> lock(g_rssMutex);
94     if (g_tidToReport.find(tid) == g_tidToReport.end()) {
95         AUDIO_INFO_LOG("Add tid in server %{public}u", tid);
96         g_tidToReport.insert(tid);
97     }
98     ScheduleReportData(pid, tid, "audio_server");
99 }
100 
OnAddResSchedService(uint32_t audioServerPid)101 void OnAddResSchedService(uint32_t audioServerPid)
102 {
103     std::lock_guard<std::mutex> lock(g_rssMutex);
104     for (auto tid : g_tidToReport) {
105         AUDIO_INFO_LOG("On add rss, report %{public}u", tid);
106         ScheduleReportData(audioServerPid, tid, "audio_server");
107     }
108 }
109 #else
ScheduleReportData(uint32_t,uint32_t,const char *)110 void ScheduleReportData(uint32_t /* pid */, uint32_t /* tid */, const char* /* bundleName*/) {};
ScheduleThreadInServer(uint32_t pid,uint32_t tid)111 void ScheduleThreadInServer(uint32_t pid, uint32_t tid) {};
UnscheduleThreadInServer(uint32_t tid)112 void UnscheduleThreadInServer(uint32_t tid) {};
OnAddResSchedService(uint32_t audioServerPid)113 void OnAddResSchedService(uint32_t audioServerPid) {};
UnscheduleReportData(uint32_t,uint32_t,const char *)114 void UnscheduleReportData(uint32_t /* pid */, uint32_t /* tid */, const char* /* bundleName*/) {};
115 #endif
116 
117 #ifdef __cplusplus
118 }
119 #endif
120 
121 namespace OHOS {
122 namespace AudioStandard {
AudioScheduleGuard(uint32_t pid,uint32_t tid,const std::string & bundleName)123 AudioScheduleGuard::AudioScheduleGuard(uint32_t pid, uint32_t tid, const std::string &bundleName)
124     : pid_(pid), tid_(tid), bundleName_(bundleName)
125 {
126     ScheduleReportData(pid, tid, bundleName.c_str());
127     isReported_ = true;
128 }
129 
AudioScheduleGuard(AudioScheduleGuard && audioScheduleGuard)130 AudioScheduleGuard::AudioScheduleGuard(AudioScheduleGuard&& audioScheduleGuard)
131     : pid_(audioScheduleGuard.pid_), tid_(audioScheduleGuard.tid_),
132     bundleName_(std::move(audioScheduleGuard.bundleName_)), isReported_(audioScheduleGuard.isReported_)
133 {
134     audioScheduleGuard.isReported_ = false;
135 }
136 
operator =(AudioScheduleGuard && audioScheduleGuard)137 AudioScheduleGuard& AudioScheduleGuard::operator=(AudioScheduleGuard&& audioScheduleGuard)
138 {
139     if (*this == audioScheduleGuard) {
140         audioScheduleGuard.isReported_ = false;
141         return *this;
142     }
143     AudioScheduleGuard temp(std::move(*this));
144     this->bundleName_ = std::move(audioScheduleGuard.bundleName_);
145     this->isReported_ = audioScheduleGuard.isReported_;
146     this->pid_ = audioScheduleGuard.pid_;
147     this->tid_ = audioScheduleGuard.tid_;
148     audioScheduleGuard.isReported_ = false;
149     return *this;
150 }
151 
~AudioScheduleGuard()152 AudioScheduleGuard::~AudioScheduleGuard()
153 {
154     if (isReported_) {
155         UnscheduleReportData(pid_, tid_, bundleName_.c_str());
156     }
157 }
158 } // namespace AudioStandard
159 } // namespace OHOS