• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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