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