1 /*
2 * Copyright (c) 2023-2025 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_affinity_manager.h"
17 #include "parameter.h"
18
19 #include "audio_errors.h"
20 #include "audio_policy_log.h"
21 #include "audio_affinity_parser.h"
22
23 using namespace std;
24
25 namespace OHOS {
26 namespace AudioStandard {
27
28 constexpr int32_t MS_PER_S = 1000;
29 constexpr int32_t NS_PER_MS = 1000000;
GetCurrentTimeMS()30 static int64_t GetCurrentTimeMS()
31 {
32 timespec tm{};
33 clock_gettime(CLOCK_MONOTONIC, &tm);
34 return tm.tv_sec * MS_PER_S + (tm.tv_nsec / NS_PER_MS);
35 }
36
ParseAffinityXml()37 void AudioAffinityManager::ParseAffinityXml()
38 {
39 unique_ptr<AudioAffinityParser> affinityParser = make_unique<AudioAffinityParser>(this);
40 if (affinityParser->LoadConfiguration()) {
41 AUDIO_INFO_LOG("Audio Affinity manager load configuration successfully.");
42 }
43 OnXmlParsingCompleted(affinityParser->GetAffinityDeviceInfo());
44 }
45
OnXmlParsingCompleted(std::vector<AffinityDeviceInfo> & xmlData)46 void AudioAffinityManager::OnXmlParsingCompleted(std::vector<AffinityDeviceInfo> &xmlData)
47 {
48 CHECK_AND_RETURN_LOG(!xmlData.empty(), "Failed to parse xml file.");
49 for (AffinityDeviceInfo deviceInfo : xmlData) {
50 if (deviceInfo.deviceFlag == OUTPUT_DEVICES_FLAG) {
51 rendererAffinityDeviceArray_.push_back(deviceInfo);
52 } else {
53 capturerAffinityDeviceArray_.push_back(deviceInfo);
54 }
55 }
56 }
57
GetRendererDevice(int32_t clientUID)58 std::shared_ptr<AudioDeviceDescriptor> AudioAffinityManager::GetRendererDevice(int32_t clientUID)
59 {
60 std::lock_guard<std::mutex> lock(rendererMapMutex_);
61 int32_t affinityClientUID = clientUID;
62 AFFINITYDEVMAP::iterator item = activeRendererDeviceMap_.find(clientUID);
63 if (item != activeRendererDeviceMap_.end()) {
64 if (item->second == nullptr) {
65 AUDIO_INFO_LOG("AudioDeviceDescriptor sptr not valid");
66 return make_shared<AudioDeviceDescriptor>();
67 }
68 shared_ptr<AudioDeviceDescriptor> desc =
69 make_shared<AudioDeviceDescriptor>(activeRendererDeviceMap_[affinityClientUID]);
70 return desc;
71 } else {
72 return make_shared<AudioDeviceDescriptor>();
73 }
74 }
75
GetCapturerDevice(int32_t clientUID)76 std::shared_ptr<AudioDeviceDescriptor> AudioAffinityManager::GetCapturerDevice(int32_t clientUID)
77 {
78 std::lock_guard<std::mutex> lock(capturerMapMutex_);
79 int32_t affinityClientUID = clientUID;
80 AFFINITYDEVMAP::iterator item = activeCapturerDeviceMap_.find(clientUID);
81 if (item != activeCapturerDeviceMap_.end()) {
82 if (item->second == nullptr) {
83 AUDIO_INFO_LOG("AudioDeviceDescriptor sptr not valid");
84 return make_shared<AudioDeviceDescriptor>();
85 }
86 shared_ptr<AudioDeviceDescriptor> desc =
87 make_shared<AudioDeviceDescriptor>(activeCapturerDeviceMap_[affinityClientUID]);
88 return desc;
89 } else {
90 return make_shared<AudioDeviceDescriptor>();
91 }
92 }
93
AddSelectRendererDevice(int32_t clientUID,const std::shared_ptr<AudioDeviceDescriptor> & desc)94 void AudioAffinityManager::AddSelectRendererDevice(
95 int32_t clientUID, const std::shared_ptr<AudioDeviceDescriptor> &desc)
96 {
97 std::lock_guard<std::mutex> lock(rendererMapMutex_);
98 CHECK_AND_RETURN_LOG(desc != nullptr, "AudioDeviceDescriptor sptr not valid");
99
100 activeRendererDeviceMap_[clientUID] = desc;
101
102 AffinityDeviceInfo affinityDeviceInfo =
103 GetAffinityDeviceInfoByDeviceType(rendererAffinityDeviceArray_, desc->getType(), desc->networkId_);
104
105 affinityDeviceInfo.chooseTimeStamp = static_cast<uint64_t>(GetCurrentTimeMS());
106
107 std::unordered_map<int32_t, AffinityDeviceInfo> affinityDeviceInfoMap =
108 GetActiveAffinityDeviceMapByGroupName(activeRendererGroupAffinityMap_, affinityDeviceInfo.groupName);
109
110 affinityDeviceInfoMap[clientUID] = affinityDeviceInfo;
111 activeRendererGroupAffinityMap_[affinityDeviceInfo.groupName] = affinityDeviceInfoMap;
112 }
113
AddSelectCapturerDevice(int32_t clientUID,const std::shared_ptr<AudioDeviceDescriptor> & desc)114 void AudioAffinityManager::AddSelectCapturerDevice(
115 int32_t clientUID, const std::shared_ptr<AudioDeviceDescriptor> &desc)
116 {
117 std::lock_guard<std::mutex> lock(capturerMapMutex_);
118 CHECK_AND_RETURN_LOG(desc != nullptr, "AudioDeviceDescriptor sptr not valid");
119
120 activeCapturerDeviceMap_[clientUID] = desc;
121
122 AffinityDeviceInfo affinityDeviceInfo =
123 GetAffinityDeviceInfoByDeviceType(capturerAffinityDeviceArray_, desc->getType(), desc->networkId_);
124
125 affinityDeviceInfo.chooseTimeStamp = static_cast<uint64_t>(GetCurrentTimeMS());
126
127 std::unordered_map<int32_t, AffinityDeviceInfo> affinityDeviceInfoMap =
128 GetActiveAffinityDeviceMapByGroupName(activeCapturerGroupAffinityMap_, affinityDeviceInfo.groupName);
129
130 affinityDeviceInfoMap[clientUID] = affinityDeviceInfo;
131 activeCapturerGroupAffinityMap_[affinityDeviceInfo.groupName] = affinityDeviceInfoMap;
132 }
133
DelSelectRendererDevice(int32_t clientUID)134 void AudioAffinityManager::DelSelectRendererDevice(int32_t clientUID)
135 {
136 std::lock_guard<std::mutex> lock(rendererMapMutex_);
137 AFFINITYDEVMAP::iterator item = activeRendererDeviceMap_.find(clientUID);
138 if (item != activeRendererDeviceMap_.end()) {
139 CHECK_AND_RETURN_LOG(item->second != nullptr, "AudioDeviceDescriptor sptr not valid");
140 DelActiveGroupAffinityMap(clientUID, item->second->getType(), item->second->networkId_,
141 rendererAffinityDeviceArray_, activeRendererGroupAffinityMap_);
142 activeRendererDeviceMap_.erase(item);
143 }
144 }
145
DelSelectCapturerDevice(int32_t clientUID)146 void AudioAffinityManager::DelSelectCapturerDevice(int32_t clientUID)
147 {
148 std::lock_guard<std::mutex> lock(capturerMapMutex_);
149 AFFINITYDEVMAP::iterator item = activeCapturerDeviceMap_.find(clientUID);
150 if (item != activeCapturerDeviceMap_.end()) {
151 CHECK_AND_RETURN_LOG(item->second != nullptr, "AudioDeviceDescriptor sptr not valid");
152 DelActiveGroupAffinityMap(clientUID, item->second->getType(), item->second->networkId_,
153 capturerAffinityDeviceArray_, activeCapturerGroupAffinityMap_);
154 activeCapturerDeviceMap_.erase(item);
155 }
156 }
157
RemoveOfflineRendererDevice(const AudioDeviceDescriptor & updateDesc)158 void AudioAffinityManager::RemoveOfflineRendererDevice(const AudioDeviceDescriptor &updateDesc)
159 {
160 std::lock_guard<std::mutex> lock(rendererMapMutex_);
161 AFFINITYDEVMAP::iterator item = activeRendererDeviceMap_.begin();
162 while (item != activeRendererDeviceMap_.end()) {
163 CHECK_AND_RETURN_LOG(item->second != nullptr, "AudioDeviceDescriptor sptr not valid");
164 if (item->second->deviceType_ == updateDesc.deviceType_ &&
165 item->second->networkId_ == updateDesc.networkId_) {
166 DelActiveGroupAffinityMap(item->first, item->second->getType(), item->second->networkId_,
167 rendererAffinityDeviceArray_, activeRendererGroupAffinityMap_);
168 item = activeRendererDeviceMap_.erase(item);
169 } else {
170 ++item;
171 }
172 }
173 }
174
RemoveOfflineCapturerDevice(const AudioDeviceDescriptor & updateDesc)175 void AudioAffinityManager::RemoveOfflineCapturerDevice(const AudioDeviceDescriptor &updateDesc)
176 {
177 std::lock_guard<std::mutex> lock(capturerMapMutex_);
178 AFFINITYDEVMAP::iterator item = activeCapturerDeviceMap_.begin();
179 while (item != activeCapturerDeviceMap_.end()) {
180 CHECK_AND_RETURN_LOG(item->second != nullptr, "AudioDeviceDescriptor sptr not valid");
181 if (item->second->deviceType_ == updateDesc.deviceType_ &&
182 item->second->networkId_ == updateDesc.networkId_) {
183 DelActiveGroupAffinityMap(item->first, item->second->getType(), item->second->networkId_,
184 capturerAffinityDeviceArray_, activeCapturerGroupAffinityMap_);
185 item = activeCapturerDeviceMap_.erase(item);
186 } else {
187 ++item;
188 }
189 }
190 }
191
GetAffinityDeviceInfoByDeviceType(const std::vector<AffinityDeviceInfo> & affinityDeviceInfoArray,const DeviceType & deviceType,const std::string & networkID)192 AffinityDeviceInfo AudioAffinityManager::GetAffinityDeviceInfoByDeviceType(
193 const std::vector<AffinityDeviceInfo> &affinityDeviceInfoArray, const DeviceType &deviceType,
194 const std::string &networkID)
195 {
196 AffinityDeviceInfo affinityDeviceInfo = {};
197 std::vector<AffinityDeviceInfo>::const_iterator item = affinityDeviceInfoArray.begin();
198 while (item != rendererAffinityDeviceArray_.end()) {
199 if (networkID == item->networkID && deviceType == item->deviceType) {
200 affinityDeviceInfo = *item;
201 break;
202 }
203 ++item;
204 }
205 return affinityDeviceInfo;
206 }
207
GetActiveAffinityDeviceMapByGroupName(const AFFINITYDEVINFOMAP & activeGroupNameMap,const std::string & groupName)208 std::unordered_map<int32_t, AffinityDeviceInfo> AudioAffinityManager::GetActiveAffinityDeviceMapByGroupName(
209 const AFFINITYDEVINFOMAP &activeGroupNameMap, const std::string &groupName)
210 {
211 std::unordered_map<int32_t, AffinityDeviceInfo> affinityDeviceInfoMap = {};
212 AFFINITYDEVINFOMAP::const_iterator itemGroup = activeGroupNameMap.find(groupName);
213 if (itemGroup != activeGroupNameMap.end()) {
214 affinityDeviceInfoMap = itemGroup->second;
215 }
216 return affinityDeviceInfoMap;
217 }
218
GetAffinityClientUID(const int32_t & clientUID,const DeviceType & deviceType,const std::string & networkID,const std::vector<AffinityDeviceInfo> & affinityDeviceInfoArray,AFFINITYDEVINFOMAP & activeGroupNameMap)219 int32_t AudioAffinityManager::GetAffinityClientUID(const int32_t &clientUID, const DeviceType &deviceType,
220 const std::string &networkID, const std::vector<AffinityDeviceInfo> &affinityDeviceInfoArray,
221 AFFINITYDEVINFOMAP &activeGroupNameMap)
222 {
223 AffinityDeviceInfo affinityDeviceInfo =
224 GetAffinityDeviceInfoByDeviceType(affinityDeviceInfoArray, deviceType, networkID);
225
226 std::unordered_map<int32_t, AffinityDeviceInfo> affinityDeviceInfoMap =
227 GetActiveAffinityDeviceMapByGroupName(activeGroupNameMap, affinityDeviceInfo.groupName);
228
229 return GetAffinityClientUID(clientUID, affinityDeviceInfoMap);
230 }
231
GetAffinityClientUID(const int32_t & clientUID,std::unordered_map<int32_t,AffinityDeviceInfo> & affinityDeviceInfoMap)232 int32_t AudioAffinityManager::GetAffinityClientUID(
233 const int32_t &clientUID, std::unordered_map<int32_t, AffinityDeviceInfo> &affinityDeviceInfoMap)
234 {
235 std::unordered_map<int32_t, AffinityDeviceInfo>::iterator item = affinityDeviceInfoMap.find(clientUID);
236 if (item != affinityDeviceInfoMap.end() && item->second.SupportedConcurrency) {
237 return clientUID;
238 }
239 int32_t affinityClientID = 0;
240 uint64_t chooseTimeStamp = 0;
241 item = affinityDeviceInfoMap.begin();
242 while (item != affinityDeviceInfoMap.end()) {
243 if (!item->second.SupportedConcurrency && chooseTimeStamp < item->second.chooseTimeStamp) {
244 chooseTimeStamp = item->second.chooseTimeStamp;
245 affinityClientID = item->first;
246 }
247 ++item;
248 }
249 return affinityClientID;
250 }
251
DelActiveGroupAffinityMap(const int32_t & clientUID,std::unordered_map<int32_t,AffinityDeviceInfo> & affinityDeviceInfoMap)252 void AudioAffinityManager::DelActiveGroupAffinityMap(const int32_t &clientUID,
253 std::unordered_map<int32_t, AffinityDeviceInfo> &affinityDeviceInfoMap)
254 {
255 std::unordered_map<int32_t, AffinityDeviceInfo>::iterator item = affinityDeviceInfoMap.find(clientUID);
256 if (item != affinityDeviceInfoMap.end()) {
257 affinityDeviceInfoMap.erase(item);
258 }
259 }
260
DelActiveGroupAffinityMap(const int32_t & clientUID,const DeviceType & deviceType,const std::string & networkID,std::vector<AffinityDeviceInfo> & affinityDeviceArray,AFFINITYDEVINFOMAP & activeGroupNameMap)261 void AudioAffinityManager::DelActiveGroupAffinityMap(const int32_t &clientUID, const DeviceType &deviceType,
262 const std::string &networkID, std::vector<AffinityDeviceInfo> &affinityDeviceArray,
263 AFFINITYDEVINFOMAP &activeGroupNameMap)
264 {
265 AffinityDeviceInfo affinityDeviceInfo =
266 GetAffinityDeviceInfoByDeviceType(affinityDeviceArray, deviceType, networkID);
267 std::unordered_map<int32_t, AffinityDeviceInfo> affinityDeviceInfoMap =
268 GetActiveAffinityDeviceMapByGroupName(activeGroupNameMap, affinityDeviceInfo.groupName);
269 DelActiveGroupAffinityMap(clientUID, affinityDeviceInfoMap);
270 activeGroupNameMap[affinityDeviceInfo.groupName] = affinityDeviceInfoMap;
271 }
272 } // namespace AudioStandard
273 } // namespace OHOS
274
275