• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #undef LOG_TAG
16 #define LOG_TAG "AudioZone"
17 
18 #include "audio_info.h"
19 #include "audio_zone.h"
20 #include "audio_log.h"
21 #include "audio_errors.h"
22 
23 namespace OHOS {
24 namespace AudioStandard {
GenerateZoneId()25 static int32_t GenerateZoneId()
26 {
27     static int32_t genId = 1;
28     static std::mutex genLock;
29     std::unique_lock<std::mutex> lock(genLock);
30     int32_t id = genId;
31     genId++;
32     if (genId <= 0) {
33         genId = 1;
34     }
35     return id;
36 }
37 
AudioZoneBindKey(int32_t uid)38 AudioZoneBindKey::AudioZoneBindKey(int32_t uid)
39     : uid_(uid)
40 {
41 }
42 
AudioZoneBindKey(int32_t uid,const std::string & deviceTag)43 AudioZoneBindKey::AudioZoneBindKey(int32_t uid, const std::string &deviceTag)
44     : uid_(uid),
45       deviceTag_(deviceTag)
46 {
47 }
48 
AudioZoneBindKey(int32_t uid,const std::string & deviceTag,const std::string & streamTag)49 AudioZoneBindKey::AudioZoneBindKey(int32_t uid, const std::string &deviceTag, const std::string &streamTag)
50     : uid_(uid),
51       deviceTag_(deviceTag),
52       streamTag_(streamTag)
53 {
54 }
55 
AudioZoneBindKey(int32_t uid,const std::string & deviceTag,const std::string & streamTag,const StreamUsage & usage)56 AudioZoneBindKey::AudioZoneBindKey(int32_t uid, const std::string &deviceTag, const std::string &streamTag,
57     const StreamUsage &usage)
58     : uid_(uid),
59       deviceTag_(deviceTag),
60       streamTag_(streamTag),
61       usage_(usage)
62 {
63 }
64 
AudioZoneBindKey(const AudioZoneBindKey & other)65 AudioZoneBindKey::AudioZoneBindKey(const AudioZoneBindKey &other)
66 {
67     Assign(other);
68 }
69 
AudioZoneBindKey(AudioZoneBindKey && other)70 AudioZoneBindKey::AudioZoneBindKey(AudioZoneBindKey &&other)
71 {
72     Swap(std::move(other));
73 }
74 
operator =(const AudioZoneBindKey & other)75 AudioZoneBindKey &AudioZoneBindKey::operator=(const AudioZoneBindKey &other)
76 {
77     Assign(other);
78     return *this;
79 }
80 
operator =(AudioZoneBindKey && other)81 AudioZoneBindKey &AudioZoneBindKey::operator=(AudioZoneBindKey &&other)
82 {
83     Swap(std::move(other));
84     return *this;
85 }
86 
operator ==(const AudioZoneBindKey & other) const87 bool AudioZoneBindKey::operator==(const AudioZoneBindKey &other) const
88 {
89     return this->uid_ == other.uid_ &&
90         this->deviceTag_ == other.deviceTag_ &&
91         this->streamTag_ == other.streamTag_ &&
92         this->usage_ == other.usage_;
93 }
94 
operator !=(const AudioZoneBindKey & other) const95 bool AudioZoneBindKey::operator!=(const AudioZoneBindKey &other) const
96 {
97     return !(*this == other);
98 }
99 
Assign(const AudioZoneBindKey & other)100 void AudioZoneBindKey::Assign(const AudioZoneBindKey &other)
101 {
102     this->uid_ = other.uid_;
103     this->deviceTag_ = other.deviceTag_;
104     this->streamTag_ = other.streamTag_;
105     this->usage_ = other.usage_;
106 }
107 
Swap(AudioZoneBindKey && other)108 void AudioZoneBindKey::Swap(AudioZoneBindKey &&other)
109 {
110     this->uid_ = other.uid_;
111     this->deviceTag_ = other.deviceTag_;
112     this->streamTag_ = std::move(other.streamTag_);
113     this->usage_ = other.usage_;
114 }
115 
GetUid() const116 int32_t AudioZoneBindKey::GetUid() const
117 {
118     return uid_;
119 }
120 
GetString() const121 const std::string AudioZoneBindKey::GetString() const
122 {
123     std::string str = "uid=";
124     str += std::to_string(uid_);
125     str += ",deviceTag=";
126     str += deviceTag_;
127     str += ",streamTag=";
128     str += streamTag_;
129     str += ",usage_=";
130     str += std::to_string(usage_);
131     return str;
132 }
133 
IsContain(const AudioZoneBindKey & other) const134 bool AudioZoneBindKey::IsContain(const AudioZoneBindKey &other) const
135 {
136     std::vector<AudioZoneBindKey> supportKeys = GetSupportKeys(other);
137     int32_t index = -1;
138     int32_t otherIndex = -1;
139     for (int32_t i = 0; i < static_cast<int32_t>(supportKeys.size()); i++) {
140         if (supportKeys[i] == *this) {
141             index = i;
142         }
143 
144         if (supportKeys[i] == other) {
145             otherIndex = i;
146         }
147     }
148     CHECK_AND_RETURN_RET(index != -1, false);
149     return index >= otherIndex;
150 }
151 
GetSupportKeys(int32_t uid,const std::string & deviceTag,const std::string & streamTag,const StreamUsage & usage)152 const std::vector<AudioZoneBindKey> AudioZoneBindKey::GetSupportKeys(int32_t uid, const std::string &deviceTag,
153     const std::string &streamTag, const StreamUsage &usage)
154 {
155     std::vector<AudioZoneBindKey> keys;
156     keys.push_back(AudioZoneBindKey(uid, deviceTag, streamTag, StreamUsage::STREAM_USAGE_INVALID));
157     auto pushBack = [&keys](const AudioZoneBindKey &temp) {
158         for (auto &key : keys) {
159             CHECK_AND_RETURN(key != temp);
160         }
161         keys.push_back(temp);
162     };
163     pushBack(AudioZoneBindKey(uid, "", streamTag));
164     pushBack(AudioZoneBindKey(uid));
165     pushBack(AudioZoneBindKey(uid, deviceTag));
166     pushBack(AudioZoneBindKey(INVALID_UID, "", "", usage));
167     return keys;
168 }
169 
GetSupportKeys(const AudioZoneBindKey & key)170 const std::vector<AudioZoneBindKey> AudioZoneBindKey::GetSupportKeys(const AudioZoneBindKey &key)
171 {
172     int32_t uid = key.uid_;
173     std::string deviceTag = key.deviceTag_;
174     std::string streamTag = key.streamTag_;
175     StreamUsage usage = key.usage_;
176     return GetSupportKeys(uid, deviceTag, streamTag, usage);
177 }
178 
AudioZone(std::shared_ptr<AudioZoneClientManager> manager,const std::string & name,const AudioZoneContext & context,pid_t clientPid)179 AudioZone::AudioZone(std::shared_ptr<AudioZoneClientManager> manager,
180     const std::string &name, const AudioZoneContext &context, pid_t clientPid)
181     : zoneId_(GenerateZoneId()),
182       name_(name),
183       clientManager_(manager),
184       zoneClientPid_(clientPid)
185 {
186 }
187 
GetId()188 int32_t AudioZone::GetId()
189 {
190     return zoneId_;
191 }
192 
IsVolumeProxyEnable()193 bool AudioZone::IsVolumeProxyEnable()
194 {
195     std::lock_guard<std::mutex> lock(zoneMutex_);
196     return isVolumeProxyEnabled_;
197 }
198 
GetDescriptor()199 const std::shared_ptr<AudioZoneDescriptor> AudioZone::GetDescriptor()
200 {
201     std::lock_guard<std::mutex> lock(zoneMutex_);
202     return GetDescriptorNoLock();
203 }
204 
GetStringDescriptor()205 const std::string AudioZone::GetStringDescriptor()
206 {
207     std::lock_guard<std::mutex> lock(zoneMutex_);
208     std::string str;
209     str += "zone name is";
210     str += name_;
211     str += "\n";
212     for (auto &key : keys_) {
213         str += "bing key ";
214         str += key.GetString();
215         str += "\n";
216     }
217     str += "zone vloume proxy is";
218     str += isVolumeProxyEnabled_ ? "enabled" : "disabled";
219     str += "\n";
220     return str;
221 }
222 
GetName()223 const std::string AudioZone::GetName()
224 {
225     return name_;
226 }
227 
GetDescriptorNoLock()228 const std::shared_ptr<AudioZoneDescriptor> AudioZone::GetDescriptorNoLock()
229 {
230     std::shared_ptr<AudioZoneDescriptor> descriptor = std::make_shared<AudioZoneDescriptor>();
231     CHECK_AND_RETURN_RET_LOG(descriptor != nullptr, nullptr, "descriptor is nullptr");
232 
233     descriptor->zoneId_ = zoneId_;
234     descriptor->name_ = name_;
235     for (const auto &key : keys_) {
236         descriptor->uids_.insert(key.GetUid());
237     }
238     for (const auto &it : devices_) {
239         descriptor->devices_.emplace_back(it.first);
240     }
241     return descriptor;
242 }
243 
BindByKey(const AudioZoneBindKey & key)244 void AudioZone::BindByKey(const AudioZoneBindKey &key)
245 {
246     std::lock_guard<std::mutex> lock(zoneMutex_);
247     for (auto itKey = keys_.begin(); itKey != keys_.end();) {
248         CHECK_AND_RETURN_LOG(!itKey->IsContain(key), "exist low key %{public}s to %{public}s for zone %{public}d",
249             itKey->GetString().c_str(), key.GetString().c_str(), zoneId_);
250         if (key.IsContain(*itKey)) {
251             AUDIO_INFO_LOG("erase high key %{public}s to %{public}s for zone %{public}d",
252                 itKey->GetString().c_str(), key.GetString().c_str(), zoneId_);
253             keys_.erase(itKey++);
254         } else {
255             ++itKey;
256         }
257     }
258     keys_.emplace_back(key);
259     AUDIO_INFO_LOG("bind key %{public}s to zone %{public}d", key.GetString().c_str(), zoneId_);
260     for (auto &temp : keys_) {
261         AUDIO_DEBUG_LOG("zone %{public}d bind key %{public}s", zoneId_, temp.GetString().c_str());
262     }
263     SendZoneChangeEvent(AudioZoneChangeReason::BIND_NEW_APP);
264 }
265 
RemoveKey(const AudioZoneBindKey & key)266 void AudioZone::RemoveKey(const AudioZoneBindKey &key)
267 {
268     std::lock_guard<std::mutex> lock(zoneMutex_);
269     auto itKey = std::find(keys_.begin(), keys_.end(), key);
270     CHECK_AND_RETURN_LOG(itKey != keys_.end(), "key %{public}s not exist for zone %{public}d",
271         key.GetString().c_str(), zoneId_);
272 
273     AUDIO_INFO_LOG("remove key %{public}s for zone %{public}d", key.GetString().c_str(), zoneId_);
274     keys_.erase(itKey);
275     for (auto &temp : keys_) {
276         AUDIO_DEBUG_LOG("zone %{public}d bind key %{public}s", zoneId_, temp.GetString().c_str());
277     }
278     SendZoneChangeEvent(AudioZoneChangeReason::UNBIND_APP);
279 }
280 
IsContainKey(const AudioZoneBindKey & key)281 bool AudioZone::IsContainKey(const AudioZoneBindKey &key)
282 {
283     std::lock_guard<std::mutex> lock(zoneMutex_);
284     for (const auto &it : keys_) {
285         if (it == key) {
286             return true;
287         }
288     }
289     return false;
290 }
291 
AddDeviceDescriptor(const std::vector<std::shared_ptr<AudioDeviceDescriptor>> & devices)292 int32_t AudioZone::AddDeviceDescriptor(const std::vector<std::shared_ptr<AudioDeviceDescriptor>> &devices)
293 {
294     std::lock_guard<std::mutex> lock(zoneMutex_);
295     for (const auto &device : devices) {
296         CHECK_AND_RETURN_RET_LOG(device != nullptr, ERR_INVALID_PARAM, "device is nullptr");
297         auto findDevice = [&device] (const std::pair<std::shared_ptr<AudioDeviceDescriptor>, bool> &item) {
298             return device->IsSameDeviceDesc(*(item.first));
299         };
300 
301         auto itDev = std::find_if(devices_.begin(), devices_.end(), findDevice);
302         if (itDev != devices_.end()) {
303             AUDIO_WARNING_LOG("add duplicate  device %{public}d,%{public}d,%{public}s to zone %{public}d",
304                 device->deviceType_, device->deviceId_, device->deviceName_.c_str(), zoneId_);
305         } else {
306             std::vector<std::shared_ptr<AudioDeviceDescriptor>> connectDevices;
307             AudioConnectedDevice::GetInstance().GetAllConnectedDeviceByType(device->networkId_,
308                 device->deviceType_, device->macAddress_, device->deviceRole_, connectDevices);
309             devices_.emplace_back(std::make_pair(device, connectDevices.size() != 0));
310             AUDIO_INFO_LOG("add device %{public}d,%{public}d,%{public}s to zone %{public}d",
311                 device->deviceType_, device->deviceId_, device->deviceName_.c_str(), zoneId_);
312         }
313     }
314     return SUCCESS;
315 }
316 
RemoveDeviceDescriptor(const std::vector<std::shared_ptr<AudioDeviceDescriptor>> & devices)317 int32_t AudioZone::RemoveDeviceDescriptor(const std::vector<std::shared_ptr<AudioDeviceDescriptor>> &devices)
318 {
319     std::lock_guard<std::mutex> lock(zoneMutex_);
320     for (const auto &device : devices) {
321         CHECK_AND_RETURN_RET_LOG(device != nullptr, ERR_INVALID_PARAM, "device is nullptr");
322         auto findDevice = [device] (const std::pair<std::shared_ptr<AudioDeviceDescriptor>, bool> &item) {
323             return device->IsSameDeviceDesc(*(item.first));
324         };
325 
326         auto itDev = std::find_if(devices_.begin(), devices_.end(), findDevice);
327         CHECK_AND_CONTINUE(itDev != devices_.end());
328 
329         devices_.erase(itDev);
330         AUDIO_INFO_LOG("remove device %{public}d,%{public}d,%{public}s from zone %{public}d",
331             device->deviceType_, device->deviceId_, device->deviceName_.c_str(), zoneId_);
332     }
333     return SUCCESS;
334 }
335 
UpdateDeviceDescriptor(const std::shared_ptr<AudioDeviceDescriptor> device)336 int32_t AudioZone::UpdateDeviceDescriptor(const std::shared_ptr<AudioDeviceDescriptor> device)
337 {
338     std::lock_guard<std::mutex> lock(zoneMutex_);
339     CHECK_AND_RETURN_RET_LOG(device != nullptr, ERR_INVALID_PARAM, "device is nullptr");
340     auto findDevice = [&device] (const std::pair<std::shared_ptr<AudioDeviceDescriptor>, bool> &item) {
341         return device->IsSameDeviceDesc(*(item.first));
342     };
343     auto itDev = std::find_if(devices_.begin(), devices_.end(), findDevice);
344     CHECK_AND_RETURN_RET_LOG(itDev != devices_.end(), ERROR,
345         "update device %{public}d,%{public}d,%{public}s not exist for zone %{public}d",
346         device->deviceType_, device->deviceId_, device->deviceName_.c_str(), zoneId_);
347 
348     devices_.erase(itDev);
349     std::vector<std::shared_ptr<AudioDeviceDescriptor>> connectDevices;
350         AudioConnectedDevice::GetInstance().GetAllConnectedDeviceByType(device->networkId_,
351             device->deviceType_, device->macAddress_, device->deviceRole_, connectDevices);
352     devices_.emplace_back(std::make_pair(device, connectDevices.size() != 0));
353     AUDIO_INFO_LOG("add device %{public}d,%{public}d,%{public}s to zone %{public}d",
354         device->deviceType_, device->deviceId_, device->deviceName_.c_str(), zoneId_);
355     return SUCCESS;
356 }
357 
EnableDeviceDescriptor(std::shared_ptr<AudioDeviceDescriptor> device)358 int32_t AudioZone::EnableDeviceDescriptor(std::shared_ptr<AudioDeviceDescriptor> device)
359 {
360     return SetDeviceDescriptorState(device, true);
361 }
362 
DisableDeviceDescriptor(std::shared_ptr<AudioDeviceDescriptor> device)363 int32_t AudioZone::DisableDeviceDescriptor(std::shared_ptr<AudioDeviceDescriptor> device)
364 {
365     return SetDeviceDescriptorState(device, false);
366 }
367 
SetDeviceDescriptorState(const std::shared_ptr<AudioDeviceDescriptor> device,const bool enable)368 int32_t AudioZone::SetDeviceDescriptorState(const std::shared_ptr<AudioDeviceDescriptor> device, const bool enable)
369 {
370     std::lock_guard<std::mutex> lock(zoneMutex_);
371     CHECK_AND_RETURN_RET_LOG(device != nullptr, ERROR, "device is nullptr");
372     auto findDevice = [device] (const std::pair<std::shared_ptr<AudioDeviceDescriptor>, bool> &item) {
373         return device->IsSameDeviceDesc(*(item.first));
374     };
375 
376     auto itDev = std::find_if(devices_.begin(), devices_.end(), findDevice);
377     CHECK_AND_RETURN_RET_LOG(itDev != devices_.end(), ERROR,
378         "device %{public}d,%{public}d,%{public}s not exist for zone %{public}d",
379         device->deviceType_, device->deviceId_, device->deviceName_.c_str(), zoneId_);
380 
381     itDev->second = enable;
382     AUDIO_INFO_LOG("%{public}s device %{public}d,%{public}d,%{public}s of zone %{public}d",
383         enable ? "enable" : "disable", device->deviceType_, device->deviceId_, device->deviceName_.c_str(), zoneId_);
384     return SUCCESS;
385 }
386 
IsDeviceConnect(std::shared_ptr<AudioDeviceDescriptor> device)387 bool AudioZone::IsDeviceConnect(std::shared_ptr<AudioDeviceDescriptor> device)
388 {
389     std::lock_guard<std::mutex> lock(zoneMutex_);
390     CHECK_AND_RETURN_RET_LOG(device != nullptr, false, "device is nullptr");
391     auto findDevice = [device] (const std::pair<std::shared_ptr<AudioDeviceDescriptor>, bool> &item) {
392         return device->IsSameDeviceDesc(*(item.first));
393     };
394     auto itDev = std::find_if(devices_.begin(), devices_.end(), findDevice);
395     CHECK_AND_RETURN_RET(itDev != devices_.end(), false);
396 
397     return itDev->second;
398 }
399 
FetchOutputDevices(StreamUsage streamUsage,int32_t clientUid,const RouterType & bypassType)400 std::vector<std::shared_ptr<AudioDeviceDescriptor>> AudioZone::FetchOutputDevices(StreamUsage streamUsage,
401     int32_t clientUid, const RouterType &bypassType)
402 {
403     std::lock_guard<std::mutex> lock(zoneMutex_);
404     std::vector<std::shared_ptr<AudioDeviceDescriptor>> descs;
405     for (const auto &device : devices_) {
406         if (device.second && device.first->deviceRole_ == OUTPUT_DEVICE) {
407             descs.emplace_back(device.first);
408             return descs;
409         }
410     }
411     return descs;
412 }
413 
FetchInputDevice(SourceType sourceType,int32_t clientUid)414 std::shared_ptr<AudioDeviceDescriptor> AudioZone::FetchInputDevice(SourceType sourceType, int32_t clientUid)
415 {
416     std::lock_guard<std::mutex> lock(zoneMutex_);
417     for (const auto &device : devices_) {
418         if (device.second && device.first->deviceRole_ == INPUT_DEVICE) {
419             return device.first;
420         }
421     }
422     return nullptr;
423 }
424 
EnableChangeReport(pid_t clientPid,bool enable)425 int32_t AudioZone::EnableChangeReport(pid_t clientPid, bool enable)
426 {
427     std::lock_guard<std::mutex> lock(zoneMutex_);
428     if (enable) {
429         changeReportClientList_.insert(clientPid);
430     } else {
431         changeReportClientList_.erase(clientPid);
432     }
433     AUDIO_INFO_LOG(" %{public}s zone %{public}d change report to client %{public}d",
434         enable ? "enable" : "disable", zoneId_, clientPid);
435     return SUCCESS;
436 }
437 
SendZoneChangeEvent(AudioZoneChangeReason reason)438 void AudioZone::SendZoneChangeEvent(AudioZoneChangeReason reason)
439 {
440     CHECK_AND_RETURN_LOG(clientManager_ != nullptr, "clientManager is nullptr");
441     for (auto &pid : changeReportClientList_) {
442         clientManager_->SendZoneChangeEvent(pid, this->GetDescriptorNoLock(), reason);
443     }
444 }
445 
EnableSystemVolumeProxy(pid_t clientPid,bool enable)446 int32_t AudioZone::EnableSystemVolumeProxy(pid_t clientPid, bool enable)
447 {
448     std::lock_guard<std::mutex> lock(zoneMutex_);
449     volumeProxyClientPid_ = clientPid;
450     isVolumeProxyEnabled_ = enable;
451     AUDIO_INFO_LOG("volume proxy is %{public}s by %{public}d",
452         enable ? "enable" : "disable", clientPid);
453     return SUCCESS;
454 }
455 
SetSystemVolumeLevel(AudioVolumeType volumeType,int32_t volumeLevel,int32_t volumeFlag)456 int32_t AudioZone::SetSystemVolumeLevel(AudioVolumeType volumeType,
457     int32_t volumeLevel, int32_t volumeFlag)
458 {
459     std::shared_ptr<AudioZoneClientManager> mgr;
460     {
461         std::lock_guard<std::mutex> lock(zoneMutex_);
462         CHECK_AND_RETURN_RET_LOG(clientManager_ != nullptr, ERROR, "clientManager is nullptr");
463         CHECK_AND_RETURN_RET_LOG(isVolumeProxyEnabled_, ERROR, "volume proxy is not enable");
464 
465         mgr = clientManager_;
466     }
467     return mgr->SetSystemVolumeLevel(volumeProxyClientPid_, zoneId_,
468         volumeType, volumeLevel, volumeFlag);
469 }
470 
GetSystemVolumeLevel(AudioVolumeType volumeType)471 int32_t AudioZone::GetSystemVolumeLevel(AudioVolumeType volumeType)
472 {
473     std::shared_ptr<AudioZoneClientManager> mgr;
474     {
475         std::lock_guard<std::mutex> lock(zoneMutex_);
476         CHECK_AND_RETURN_RET_LOG(clientManager_ != nullptr, ERROR, "clientManager is nullptr");
477         CHECK_AND_RETURN_RET_LOG(isVolumeProxyEnabled_, ERROR, "volume proxy is not enable");
478 
479         mgr = clientManager_;
480     }
481     return mgr->GetSystemVolumeLevel(volumeProxyClientPid_, zoneId_, volumeType);
482 }
483 
GetClientPid()484 pid_t AudioZone::GetClientPid()
485 {
486     return zoneClientPid_;
487 }
488 } // namespace AudioStandard
489 } // namespace OHOS