From 43a0fafaff44fd5d93186b9299221cfc4b99b605 Mon Sep 17 00:00:00 2001 From: zhuzhihui7 Date: Fri, 14 Feb 2025 17:37:11 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9F=B3=E9=A2=91=E4=BB=A3=E7=A0=81=E6=8F=90?= =?UTF-8?q?=E4=BA=A4allconnect?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhuzhihui7 --- common/include/daudio_constants.h | 2 + common/include/daudio_errorcode.h | 5 + .../micclient/include/dmic_client.h | 2 + .../audioclient/micclient/src/dmic_client.cpp | 5 +- .../spkclient/include/dspeaker_client.h | 4 + .../spkclient/src/dspeaker_client.cpp | 5 + .../allconnect/include/daudio_block_obj.h | 64 ++++ .../daudio_collaboration_manager_capi.h | 91 +++++ .../distributed_audio_allconnect_manager.h | 78 +++++ .../distributed_audio_allconnect_manager.cpp | 326 ++++++++++++++++++ .../managersink/include/daudio_sink_manager.h | 15 +- .../managersink/src/daudio_sink_dev.cpp | 10 + .../managersink/src/daudio_sink_manager.cpp | 133 +++++++ .../managersource/include/daudio_io_dev.h | 4 +- .../managersource/include/daudio_source_dev.h | 2 + .../include/daudio_source_manager.h | 12 +- .../managersource/include/dmic_dev.h | 3 +- .../managersource/include/dspeaker_dev.h | 5 +- .../managersource/src/daudio_source_dev.cpp | 108 +++++- .../src/daudio_source_manager.cpp | 90 +++++ .../managersource/src/dmic_dev.cpp | 10 +- .../managersource/src/dspeaker_dev.cpp | 10 +- services/audiomanager/servicesink/BUILD.gn | 5 + .../servicesink/src/daudio_sink_service.cpp | 32 +- services/audiomanager/servicesource/BUILD.gn | 6 +- .../src/daudio_source_service.cpp | 40 ++- services/common/audioparam/audio_event.h | 2 + 27 files changed, 1046 insertions(+), 23 deletions(-) create mode 100644 services/audiomanager/allconnect/include/daudio_block_obj.h create mode 100644 services/audiomanager/allconnect/include/daudio_collaboration_manager_capi.h create mode 100644 services/audiomanager/allconnect/include/distributed_audio_allconnect_manager.h create mode 100644 services/audiomanager/allconnect/src/distributed_audio_allconnect_manager.cpp diff --git a/common/include/daudio_constants.h b/common/include/daudio_constants.h index 48f1de95..293186ea 100644 --- a/common/include/daudio_constants.h +++ b/common/include/daudio_constants.h @@ -169,6 +169,8 @@ const std::string SESSIONNAME_SPK_SINK = "ohos.dhardware.daudio.dspeaker_receive const std::string SESSIONNAME_SPK_SOURCE = "ohos.dhardware.daudio.dspeaker_sender.avtrans.control"; const std::string SESSIONNAME_MIC_SOURCE = "ohos.dhardware.daudio.dmic_receiver.avtrans.control"; const std::string SESSIONNAME_MIC_SINK = "ohos.dhardware.daudio.dmic_sender.avtrans.control"; +const std::string SPK_SERVICE_NAME = "DistributedSpeaker"; +const std::string MIC_SERVICE_NAME = "DistributedMicrophone"; } // namespace DistributedHardware } // namespace OHOS #endif // OHOS_DAUDIO_CONSTANTS_H diff --git a/common/include/daudio_errorcode.h b/common/include/daudio_errorcode.h index a7dbe894..70d53fb5 100644 --- a/common/include/daudio_errorcode.h +++ b/common/include/daudio_errorcode.h @@ -72,6 +72,11 @@ enum DAudioErrorCode { ERR_DH_AUDIO_HDI_INVALID_PARAM = ERR_DH_AUDIO_BASE + 45, ERR_DH_AV_TRANS_CREATE_CHANNEL_FAILED = ERR_DH_AUDIO_BASE + 46, ERR_DH_AUDIO_ACCESS_PERMISSION_CHECK_FAIL = ERR_DH_AUDIO_BASE + 47, + + ERR_DH_AUDIO_APPLY_RESULT = ERR_DH_AUDIO_BASE + 48, + ERR_DH_AUDIO_ERR_DLOPEN = ERR_DH_AUDIO_BASE + 49, + ERR_DH_AUDIO_ERR_PUBLISH_STATE = ERR_DH_AUDIO_BASE + 50, + ERR_DH_AUDIO_ERR_ALLCONNECT = ERR_DH_AUDIO_BASE + 51, }; } // namespace DistributedHardware } // namespace OHOS diff --git a/services/audioclient/micclient/include/dmic_client.h b/services/audioclient/micclient/include/dmic_client.h index 5488621e..1381f57b 100644 --- a/services/audioclient/micclient/include/dmic_client.h +++ b/services/audioclient/micclient/include/dmic_client.h @@ -71,6 +71,8 @@ public: void OnReadData(size_t length) override; int32_t PauseCapture(); int32_t ResumeCapture(); + + std::shared_ptr GetTrans(); private: void CaptureThreadRunning(); diff --git a/services/audioclient/micclient/src/dmic_client.cpp b/services/audioclient/micclient/src/dmic_client.cpp index cbed629c..bb8d8191 100644 --- a/services/audioclient/micclient/src/dmic_client.cpp +++ b/services/audioclient/micclient/src/dmic_client.cpp @@ -408,7 +408,10 @@ int32_t DMicClient::StopCapture() } return DH_SUCCESS; } - +std::shared_ptr DMicClient::GetTrans() +{ + return micTrans_; +} void DMicClient::SetAttrs(const std::string &devId, const std::shared_ptr &callback) { DHLOGE("Set attrs, not support yet."); diff --git a/services/audioclient/spkclient/include/dspeaker_client.h b/services/audioclient/spkclient/include/dspeaker_client.h index 22f2102c..e4f5091c 100644 --- a/services/audioclient/spkclient/include/dspeaker_client.h +++ b/services/audioclient/spkclient/include/dspeaker_client.h @@ -85,6 +85,10 @@ public: void OnCtrlTransMessage(const std::shared_ptr &message) override; void OnWriteData(size_t length) override; + + std::shared_ptr GetTrans(); + std::string GetDevId() { return devId_; }; + int32_t GetDhId() { return dhId_; }; private: std::string GetVolumeLevel(); void PlayThreadRunning(); diff --git a/services/audioclient/spkclient/src/dspeaker_client.cpp b/services/audioclient/spkclient/src/dspeaker_client.cpp index f3ce13fb..859abd20 100644 --- a/services/audioclient/spkclient/src/dspeaker_client.cpp +++ b/services/audioclient/spkclient/src/dspeaker_client.cpp @@ -246,6 +246,11 @@ int32_t DSpeakerClient::Release() return isSucess ? DH_SUCCESS : ERR_DH_AUDIO_CLIENT_RENDER_RELEASE_FAILED; } +std::shared_ptr DSpeakerClient::GetTrans() +{ + return speakerTrans_; +} + int32_t DSpeakerClient::StartRender() { DHLOGI("Start spk client."); diff --git a/services/audiomanager/allconnect/include/daudio_block_obj.h b/services/audiomanager/allconnect/include/daudio_block_obj.h new file mode 100644 index 00000000..aaa91f44 --- /dev/null +++ b/services/audiomanager/allconnect/include/daudio_block_obj.h @@ -0,0 +1,64 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ + +#ifndef DAUDIO_BLOCK_OBJECT_H +#define DAUDIO_BLOCK_OBJECT_H + +#include +#include + +namespace OHOS { +namespace DistributedHardware { +template +class DAudioBlockObject { +public: + explicit DAudioBlockObject(uint32_t interval, const T &invalid = T()) : interval_(interval), data_(invalid) + { + } + ~DAudioBlockObject() = default; + + void SetValue(T data) + { + std::lock_guard lock(mutex_); + data_ = std::move(data); + isSet_ = true; + cv_.notify_one(); + } + + T GetValue() + { + std::unique_lock lock(mutex_); + cv_.wait_for(lock, std::chrono::milliseconds(interval_), [this]() { return isSet_; }); + isSet_ = false; + T data = std::move(data_); + cv_.notify_one(); + return data; + } + + void SetInterval(uint32_t interval) + { + interval_ = interval; + } + +private: + uint32_t interval_; + bool isSet_ = false; + std::mutex mutex_; + std::condition_variable cv_; + T data_; +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif // DCAMERA_BLOCK_OBJECT_H \ No newline at end of file diff --git a/services/audiomanager/allconnect/include/daudio_collaboration_manager_capi.h b/services/audiomanager/allconnect/include/daudio_collaboration_manager_capi.h new file mode 100644 index 00000000..c5fb9edc --- /dev/null +++ b/services/audiomanager/allconnect/include/daudio_collaboration_manager_capi.h @@ -0,0 +1,91 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ + + +#ifndef DAUDIO_COLLABORATION_MANAGER_CAPI_H +#define DAUDIO_COLLABORATION_MANAGER_CAPI_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum DAudioCollaborationHardwareType { + SCM_UNKNOWN_TYPE = 0, + SCM_DISPLAY = 1, + SCM_MIC = 2, + SCM_SPEAKER = 3, + SCM_CAMERA = 4, +} DAudioCollaborationHardwareType; + +typedef enum DAudioCollaborationBussinessStatus { + SCM_IDLE = 1, + SCM_PREPARE = 2, + SCM_CONNECTING = 3, + SCM_CONNECTED = 4 +} DAudioCollaborationBussinessStatus; + +typedef enum DAudioCollaborationResultCode { + PASS = 1004720001, + REJECT = 1004720002 +} DAudioCollaborationResultCode; + +typedef struct DAudioCollaborationHardwareRequestInfo { + DAudioCollaborationHardwareType hardWareType; + bool canShare; +} DAudioCollaborationHardwareRequestInfo; + +typedef struct DAudioCollaborationCommunicationRequestInfo { + int32_t minBandwidth; + int32_t maxLatency; + int32_t minLatency; + int32_t maxWaitTime; + const char *dataType; +} DAudioCollaborationCommunicationRequestInfo; + +typedef struct DAudioCollaborationResourceRequestInfoSets { + uint32_t remoteHardwareListSize; + DAudioCollaborationHardwareRequestInfo *remoteHardwareList; + uint32_t localHardwareListSize; + DAudioCollaborationHardwareRequestInfo *localHardwareList; + DAudioCollaborationCommunicationRequestInfo *communicationRequest; +} DAudioCollaborationResourceRequestInfoSets; + +typedef struct DAudioCollaborationCallback { + int32_t (*onStop)(const char *peerNetworkId); + int32_t (*applyResult)(int32_t errorcode, int32_t result, const char *reason); +} DAudioCollaborationCallback; + +typedef struct DAudioCollaborationFun { + int32_t (*dAudioCollaborationPublishServiceState)(const char *peerNetworkId, const char *serviceName, + const char *extraInfo, DAudioCollaborationBussinessStatus state); + int32_t (*dAudioCollaborationApplyAdvancedResource)(const char *peerNetworkId, const char *serviceName, + DAudioCollaborationResourceRequestInfoSets *resourceRequest, + DAudioCollaborationCallback *callback); + int32_t (*dAudioCollaborationRegisterLifecycleCallback)(const char *serviceName, + DAudioCollaborationCallback *callback); + int32_t (*dAudioCollaborationUnRegisterLifecycleCallback)(const char *serviceName); +} DAudioCollaborationFun; + +int32_t DAudioCollaborationExport(DAudioCollaborationFun *exportapi); + +#ifdef __cplusplus +} +#endif + +#endif // DAUDIO_COLLABORATION_MANAGER_CAPI_H \ No newline at end of file diff --git a/services/audiomanager/allconnect/include/distributed_audio_allconnect_manager.h b/services/audiomanager/allconnect/include/distributed_audio_allconnect_manager.h new file mode 100644 index 00000000..5075d0ee --- /dev/null +++ b/services/audiomanager/allconnect/include/distributed_audio_allconnect_manager.h @@ -0,0 +1,78 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ + +#ifndef DISTRIBUTEDAUDIO_ALL_CONNECT_MANAGER_H +#define DISTRIBUTEDAUDIO_ALL_CONNECT_MANAGER_H + +#include +#include +#include + +#include "daudio_block_obj.h" +#include "daudio_collaboration_manager_capi.h" +#include "daudio_errorcode.h" + +namespace OHOS { +namespace DistributedHardware { +class DAudioAllConnectManager { +public: + static DAudioAllConnectManager &GetInstance(); + int32_t InitDAudioAllConnectManager(const std::string &serviceName); + int32_t UnInitDAudioAllConnectManager(const std::string &serviceName); + int32_t PublishServiceState(const std::string &peerNetworkId, + DAudioCollaborationBussinessStatus state, const std::string &serviceName); + int32_t ApplyAdvancedResource(const std::string &peerNetworkId, + DAudioCollaborationResourceRequestInfoSets *resourceRequest, const std::string &serviceName); + std::shared_ptr BuildResourceRequest(bool bSpeaker); + static bool IsSpkInited(); + static bool IsMicInited(); + +private: + DAudioAllConnectManager(); + ~DAudioAllConnectManager() = default; + int32_t GetAllConnectSoLoad(); + int32_t RegisterLifecycleCallback(const std::string &serviceName); + int32_t UnRegisterLifecycleCallback(const std::string &serviceName); + + static int32_t OnStop(const char *peerNetworkId); + static int32_t ApplyResult(int32_t errorcode, int32_t result, const char *reason); + + std::mutex allConnectLock_; + void *dllHandle_ = nullptr; + + DAudioCollaborationFun allConnect_ = { + .dAudioCollaborationPublishServiceState = nullptr, + .dAudioCollaborationApplyAdvancedResource = nullptr, + .dAudioCollaborationRegisterLifecycleCallback = nullptr, + .dAudioCollaborationUnRegisterLifecycleCallback = nullptr, + }; + DAudioCollaborationCallback allConnectCallback_; + std::shared_ptr remoteHardwareList_; + std::shared_ptr localHardwareList_; + std::shared_ptr communicationRequest_; + + static std::shared_ptr> applyResultBlock_; + static constexpr uint32_t BLOCK_INTERVAL_ALLCONNECT = 60 * 1000; + static inline const std::string SERVICE_NAME {"DistributedAudio"}; + + static bool spkIsInited_; + static std::mutex spkInitedLock_; + static bool micIsInited_; + static std::mutex micInitedLock_; +}; + +} // namespace DistributedHardware +} // namespace OHOS +#endif // DISTRIBUTEDAUDIO_ALL_CONNECT_MANAGER_H \ No newline at end of file diff --git a/services/audiomanager/allconnect/src/distributed_audio_allconnect_manager.cpp b/services/audiomanager/allconnect/src/distributed_audio_allconnect_manager.cpp new file mode 100644 index 00000000..fd17cd42 --- /dev/null +++ b/services/audiomanager/allconnect/src/distributed_audio_allconnect_manager.cpp @@ -0,0 +1,326 @@ +/* +* Copyright (c) 2024 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + */ + +#include "distributed_audio_allconnect_manager.h" + +#include +#include +#include +#include +#include "daudio_log.h" +#ifdef AUDIO_ALLCONNECT_SOURCE +#include "daudio_source_manager.h" +#endif +#ifdef AUDIO_ALLCONNECT_SINK +#include "daudio_sink_manager.h" +#endif +#include "daudio_errorcode.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "DAudioAllConnect" + +namespace OHOS { +namespace DistributedHardware { +#ifdef __LP64__ +constexpr const char *ALL_CONNECT_SO_PATH = "/system/lib64/"; +#else +constexpr const char *ALL_CONNECT_SO_PATH = "/system/lib/"; +#endif +constexpr const char *ALL_CONNECT_SO_NAME = "libcfwk_allconnect_client.z.so"; +std::shared_ptr> DAudioAllConnectManager::applyResultBlock_; +constexpr int32_t QOS_TYPE_MIN_BW = 40 * 1024 * 1024; +constexpr int32_t QOS_TYPE_MAX_LATENCY = 4000; +constexpr int32_t QOS_TYPE_MIN_LATENCY = 2000; +bool DAudioAllConnectManager::spkIsInited_ = false; +std::mutex DAudioAllConnectManager::spkInitedLock_; +bool DAudioAllConnectManager::micIsInited_ = false; +std::mutex DAudioAllConnectManager::micInitedLock_; + +DAudioAllConnectManager::DAudioAllConnectManager() +{ + allConnectCallback_.onStop = &DAudioAllConnectManager::OnStop; + allConnectCallback_.applyResult = &DAudioAllConnectManager::ApplyResult; +} + +DAudioAllConnectManager &DAudioAllConnectManager::GetInstance() +{ + static DAudioAllConnectManager instance; + return instance; +} + +int32_t DAudioAllConnectManager::InitDAudioAllConnectManager(const std::string &serviceName) +{ + DHLOGI("DAudio allconnect InitDAudioAllConnectManager begin"); + int32_t ret = GetAllConnectSoLoad(); + if (ret != DAudioErrorCode::DH_SUCCESS) { + DHLOGE("DAudio allconnect InitDAudioAllConnectManager failed, so not exist or load so error, ret %{public}d", + ret); + return ret; + } + + ret = RegisterLifecycleCallback(serviceName); + if (ret != DAudioErrorCode::DH_SUCCESS) { + DHLOGE("DAudio allconnect InitDAudioAllConnectManager failed, register lifecycle error,ret %{public}d", + ret); + return ret; + } + + if (serviceName == SPK_SERVICE_NAME) { + spkIsInited_ = true; + } else { + micIsInited_ = true; + } + + DHLOGI("DAudio allconnect InitDAudioAllConnectManager success"); + return DAudioErrorCode::DH_SUCCESS; +} + +int32_t DAudioAllConnectManager::UnInitDAudioAllConnectManager(const std::string &serviceName) +{ + DHLOGI("DAudio allconnect UnInitDAudioAllConnectManager begin"); + int32_t ret = UnRegisterLifecycleCallback(serviceName); + if (ret != DAudioErrorCode::DH_SUCCESS) { + DHLOGE("DAudio allconnect UnInitDAudioAllConnectManager failed, unregister error,ret %{public}d", ret); + } + dlclose(dllHandle_); + dllHandle_ = nullptr; + if (serviceName == SPK_SERVICE_NAME) { + spkIsInited_ = false; + } else { + micIsInited_ = false; + } + return ret; +} + +bool DAudioAllConnectManager::IsSpkInited() +{ + std::lock_guard lock(spkInitedLock_); + return spkIsInited_; +} + +bool DAudioAllConnectManager::IsMicInited() +{ + std::lock_guard lock(micInitedLock_); + return micIsInited_; +} + +int32_t DAudioAllConnectManager::PublishServiceState(const std::string &peerNetworkId, + DAudioCollaborationBussinessStatus state, const std::string &serviceName) +{ + DHLOGI("DAudio allconnect PublishServiceState begin"); + std::lock_guard lock(allConnectLock_); + if (dllHandle_ == nullptr) { + DHLOGE("DAudio allconnect dllHandle_ is nullptr, all connect not support."); + return DAudioErrorCode::DH_SUCCESS; + } + if (allConnect_.dAudioCollaborationPublishServiceState == nullptr) { + DHLOGE("DAudio allconnect PublishServiceState is nullptr, all connect function not load."); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_DLOPEN; + } + + int32_t ret = allConnect_.dAudioCollaborationPublishServiceState(peerNetworkId.c_str(), + serviceName.c_str(), "", state); + if (ret != DAudioErrorCode::DH_SUCCESS) { + DHLOGE("DAudio allconnect PublishServiceState %{public}d fail, ret %{public}d", state, ret); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_PUBLISH_STATE; + } + return DAudioErrorCode::DH_SUCCESS; +} + +int32_t DAudioAllConnectManager::ApplyAdvancedResource(const std::string &peerNetworkId, + DAudioCollaborationResourceRequestInfoSets *resourceRequest, const std::string &serviceName) +{ + DHLOGI("DAudio allconnect ApplyAdvancedResource begin"); + std::lock_guard lock(allConnectLock_); + if (dllHandle_ == nullptr) { + DHLOGE("DAudio allconnect dllHandle_ is nullptr, all connect not support."); + return DAudioErrorCode::DH_SUCCESS; + } + if (allConnect_.dAudioCollaborationApplyAdvancedResource == nullptr) { + DHLOGE("DAudio allconnect PublishServiceState is nullptr, all connect function not load."); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_DLOPEN; + } + + if (applyResultBlock_ == nullptr) { + applyResultBlock_ = std::make_shared>(BLOCK_INTERVAL_ALLCONNECT, false); + } + + int32_t ret = allConnect_.dAudioCollaborationApplyAdvancedResource(peerNetworkId.c_str(), + serviceName.c_str(), resourceRequest, &allConnectCallback_); + if (ret != DAudioErrorCode::DH_SUCCESS) { + DHLOGE("DAudio allconnect ApplyAdvancedResource fail, ret %{public}d", ret); + return DAudioErrorCode::ERR_DH_AUDIO_APPLY_RESULT; + } + auto success = applyResultBlock_->GetValue(); + if (!success) { + DHLOGE("DAudio allconnect applyResult is reject"); + return DAudioErrorCode::ERR_DH_AUDIO_APPLY_RESULT; + } + return DAudioErrorCode::DH_SUCCESS; +} + +int32_t DAudioAllConnectManager::GetAllConnectSoLoad() +{ + DHLOGI("DAudio allconnect GetAllConnectSoLoad begin"); + std::lock_guard lock(allConnectLock_); + char path[PATH_MAX + 1] = {0x00}; + std::string soPathName = std::string(ALL_CONNECT_SO_PATH) + std::string(ALL_CONNECT_SO_NAME); + if (soPathName.empty() || (soPathName.length() > PATH_MAX) || + (realpath(soPathName.c_str(), path) == nullptr)) { + DHLOGE("DAudio allconnect all connect so load failed, soPath=%{public}s not exist.", soPathName.c_str()); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_DLOPEN; + } + + int32_t (*allConnectProxy)(DAudioCollaborationFun *exportapi) = nullptr; + + dllHandle_ = dlopen(path, RTLD_LAZY); + if (dllHandle_ == nullptr) { + DHLOGE("DAudio allconnect dlopen fail"); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_DLOPEN; + } + + allConnectProxy = reinterpret_cast( + dlsym(dllHandle_, "ServiceCollaborationManager_Export")); + if (allConnectProxy == nullptr) { + dlclose(dllHandle_); + dllHandle_ = nullptr; + DHLOGE("DAudio allconnect dlsym allConnectProxy fail"); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_DLOPEN; + } + + int32_t ret = allConnectProxy(&allConnect_); + if (ret != DAudioErrorCode::DH_SUCCESS) { + dlclose(dllHandle_); + dllHandle_ = nullptr; + DHLOGE("DAudio allconnect get function struct fail, ret %{public}d", ret); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_DLOPEN; + } + DHLOGI("DAudio allconnect so load success"); + return DAudioErrorCode::DH_SUCCESS; +} + +int32_t DAudioAllConnectManager::RegisterLifecycleCallback(const std::string &serviceName) +{ + DHLOGI("DAudio allconnect RegisterLifecycleCallback begin"); + std::lock_guard lock(allConnectLock_); + if (dllHandle_ == nullptr) { + DHLOGE("DAudio allconnect dllHandle_ is nullptr, all connect so has not been loaded."); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_DLOPEN; + } + if (allConnect_.dAudioCollaborationRegisterLifecycleCallback == nullptr) { + DHLOGE("DAudio allconnect RegisterLifecycleCallback is nullptr, all connect function not load."); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_DLOPEN; + } + + int32_t ret = allConnect_.dAudioCollaborationRegisterLifecycleCallback(serviceName.c_str(), + &allConnectCallback_); + if (ret != DAudioErrorCode::DH_SUCCESS) { + DHLOGE("DAudio allconnect RegisterLifecycleCallback fail, ret %{public}d", ret); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_ALLCONNECT; + } + return DAudioErrorCode::DH_SUCCESS; +} + +int32_t DAudioAllConnectManager::UnRegisterLifecycleCallback(const std::string &serviceName) +{ + DHLOGI("DAudio allconnect UnRegisterLifecycleCallback begin"); + std::lock_guard lock(allConnectLock_); + if (dllHandle_ == nullptr) { + DHLOGE("DAudio allconnect dllHandle_ is nullptr, all connect so has not been loaded."); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_DLOPEN; + } + if (allConnect_.dAudioCollaborationUnRegisterLifecycleCallback == nullptr) { + DHLOGE("DAudio allconnect RegisterLifecycleCallback is nullptr, all connect function not load."); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_DLOPEN; + } + + int32_t ret = allConnect_.dAudioCollaborationUnRegisterLifecycleCallback(serviceName.c_str()); + if (ret != DAudioErrorCode::DH_SUCCESS) { + DHLOGE("DAudio allconnect UnRegisterLifecycleCallback fail, ret %{public}d", ret); + return DAudioErrorCode::ERR_DH_AUDIO_ERR_ALLCONNECT; + } + return DAudioErrorCode::DH_SUCCESS; +} + +int32_t DAudioAllConnectManager::ApplyResult(int32_t errorcode, int32_t result, const char *reason) +{ + DHLOGI("DAudio allconnect ApplyResult begin"); + if (result != PASS) { + DHLOGE("DAudio allconnect Apply Result is Reject, errorcode is %{}d, reason is %{public}s", errorcode, reason); + applyResultBlock_->SetValue(false); + return DAudioErrorCode::ERR_DH_AUDIO_APPLY_RESULT; + } + applyResultBlock_->SetValue(true); + return DAudioErrorCode::DH_SUCCESS; +} + +int32_t DAudioAllConnectManager::OnStop(const char *peerNetworkId) +{ + DHLOGI("DAudio allconnect OnStop begin peerNetworkId:%{public}s", peerNetworkId); + #ifdef AUDIO_ALLCONNECT_SOURCE + DAudioSourceManager::GetInstance().CloseAudioWithNetWorkId(peerNetworkId); + #endif + #ifdef AUDIO_ALLCONNECT_SINK + DAudioSinkManager::GetInstance().CloseAudioWithNetWorkId(peerNetworkId); + #endif + DHLOGI("DAudio allconnect network id is %{public}s", peerNetworkId); + return DAudioErrorCode::DH_SUCCESS; +} + +std::shared_ptr DAudioAllConnectManager::BuildResourceRequest( + bool bSpeaker) +{ + auto resourceRequest = std::make_shared(); + + if (remoteHardwareList_ == nullptr) { + remoteHardwareList_ = std::make_shared(); + if (bSpeaker) { + remoteHardwareList_->hardWareType = DAudioCollaborationHardwareType::SCM_SPEAKER; + } else { + remoteHardwareList_->hardWareType = DAudioCollaborationHardwareType::SCM_MIC; + } + + remoteHardwareList_->canShare = true; + } + resourceRequest->remoteHardwareListSize = 1; + resourceRequest->remoteHardwareList = remoteHardwareList_.get(); + + if (localHardwareList_ == nullptr) { + localHardwareList_ = std::make_shared(); + if (bSpeaker) { + localHardwareList_->hardWareType = DAudioCollaborationHardwareType::SCM_SPEAKER; + } else { + remoteHardwareList_->hardWareType = DAudioCollaborationHardwareType::SCM_MIC; + } + + localHardwareList_->canShare = true; + } + resourceRequest->localHardwareListSize = 1; + resourceRequest->localHardwareList = localHardwareList_.get(); + + if (communicationRequest_ == nullptr) { + communicationRequest_ = std::make_shared(); + communicationRequest_->minBandwidth = QOS_TYPE_MIN_BW; + communicationRequest_->maxLatency = QOS_TYPE_MAX_LATENCY; + communicationRequest_->minLatency = QOS_TYPE_MIN_LATENCY; + communicationRequest_->maxWaitTime = 0; + communicationRequest_->dataType = "DATA_TYPE_AUDIO_STREAM"; + } + resourceRequest->communicationRequest = communicationRequest_.get(); + + return resourceRequest; +} +} // namespace DistributedHardware +} // namespace OHOS \ No newline at end of file diff --git a/services/audiomanager/managersink/include/daudio_sink_manager.h b/services/audiomanager/managersink/include/daudio_sink_manager.h index 99e80c23..3e8f45bc 100644 --- a/services/audiomanager/managersink/include/daudio_sink_manager.h +++ b/services/audiomanager/managersink/include/daudio_sink_manager.h @@ -73,6 +73,11 @@ public: int32_t ResumeDistributedHardware(const std::string &networkId); int32_t StopDistributedHardware(const std::string &networkId); + static void setNetworkIdSpeakerMap(const std::string &networkId, std::shared_ptr spkClient); + void CloseAudioWithNetWorkId(const std::string &networkId); + static void RemoveSpeakerNetworkId(std::shared_ptr spkClient); + static void SetNetworkIdMicMap(const std::string &networkId, std::shared_ptr micClient); + static void RemoveMicNetworkId(std::shared_ptr micClient); private: DAudioSinkManager(); ~DAudioSinkManager(); @@ -85,7 +90,9 @@ private: std::string GetUdidByNetworkId(const std::string &networkId); int32_t VerifySecurityLevel(const std::string &devId); int32_t InitAudioDevice(std::shared_ptr dev, const std::string &devId, bool isSpkOrMic); - + void NotifyWrap(const std::string &devId, const int32_t eventType, const int32_t ret); + void CloseSpeakerClient(const std::string &networkId, std::shared_ptr speakerClient); + void CloseMicClient(const std::string &networkId); private: static constexpr const char* DEVCLEAR_THREAD = "sinkClearTh"; std::mutex devMapMutex_; @@ -109,6 +116,12 @@ private: bool isCheckSecLevel_ = false; sptr ipcSinkCallback_ = nullptr; std::shared_ptr initCallback_; + + static std::map> netwkIdSpeakMap_; + static std::mutex netwkIdSpeakMapLock_; + + static std::map> netwkIdMicMap_; + static std::mutex netwkIdMicMapLock_; }; } // DistributedHardware } // OHOS diff --git a/services/audiomanager/managersink/src/daudio_sink_dev.cpp b/services/audiomanager/managersink/src/daudio_sink_dev.cpp index 97fd01f8..362c87c5 100644 --- a/services/audiomanager/managersink/src/daudio_sink_dev.cpp +++ b/services/audiomanager/managersink/src/daudio_sink_dev.cpp @@ -23,6 +23,7 @@ #include "daudio_log.h" #include "daudio_sink_manager.h" #include "daudio_util.h" +#include "distributed_audio_allconnect_manager.h" #undef DH_LOG_TAG #define DH_LOG_TAG "DAudioSinkDev" @@ -152,6 +153,9 @@ int32_t DAudioSinkDev::TaskOpenDSpeaker(const std::string &args) ret = speakerClient->SetUp(audioParam); CHECK_AND_FREE_RETURN_RET_LOG(ret != DH_SUCCESS, ret, jParam, "Setup speaker failed, ret: %{public}d.", ret); + + std::string dhIdStr = std::to_string(dhId); + DAudioSinkManager::setNetworkIdSpeakerMap(dhIdStr, speakerClient); isSpkInUse_.store(true); cJSON_Delete(jParam); return ret; @@ -178,6 +182,7 @@ int32_t DAudioSinkDev::TaskCloseDSpeaker(const std::string &args) DHLOGE("Release speaker client failed, ret: %{public}d.", ret); } spkClientMap_.erase(dhId); + DAudioSinkManager::RemoveSpeakerNetworkId(speakerClient); DHLOGI("Close speaker device task excute success."); return DH_SUCCESS; } @@ -289,6 +294,9 @@ int32_t DAudioSinkDev::TaskOpenDMic(const std::string &args) ret = micClient->SetUp(audioParam); CHECK_AND_FREE_RETURN_RET_LOG(ret != DH_SUCCESS, ERR_DH_AUDIO_FAILED, jParam, "Set up mic failed, ret: %{public}d.", ret); + + std::string dhIdStr = std::to_string(dhId); + DAudioSinkManager::SetNetworkIdMicMap(dhIdStr, micClient); ret = micClient->StartCapture(); CHECK_AND_FREE_RETURN_RET_LOG(ret != DH_SUCCESS, ERR_DH_AUDIO_FAILED, jParam, "Start capture failed, ret: %{public}d.", ret); @@ -314,6 +322,8 @@ int32_t DAudioSinkDev::TaskCloseDMic(const std::string &args) ret = micClient->Release(); CHECK_AND_LOG(ret != DH_SUCCESS, "Release mic client failed, ret: %{public}d.", ret); micClientMap_.erase(dhId); + + DAudioSinkManager::RemoveMicNetworkId(micClient); DHLOGI("Close mic device task excute success."); return DH_SUCCESS; } diff --git a/services/audiomanager/managersink/src/daudio_sink_manager.cpp b/services/audiomanager/managersink/src/daudio_sink_manager.cpp index 1a459634..8070e11e 100644 --- a/services/audiomanager/managersink/src/daudio_sink_manager.cpp +++ b/services/audiomanager/managersink/src/daudio_sink_manager.cpp @@ -23,6 +23,7 @@ #include "daudio_errorcode.h" #include "daudio_log.h" #include "daudio_util.h" +#include "distributed_audio_allconnect_manager.h" #undef DH_LOG_TAG #define DH_LOG_TAG "DAudioSinkManager" @@ -59,6 +60,12 @@ DAudioSinkManager::~DAudioSinkManager() DHLOGD("Distributed audio sink manager deconstructed."); } +std::map> DAudioSinkManager::netwkIdSpeakMap_; +std::mutex DAudioSinkManager::netwkIdSpeakMapLock_; + +std::map> DAudioSinkManager::netwkIdMicMap_; +std::mutex DAudioSinkManager::netwkIdMicMapLock_; + int32_t DAudioSinkManager::Init(const sptr &sinkCallback) { DHLOGI("Init audio sink manager."); @@ -564,6 +571,132 @@ int32_t DAudioSinkManager::VerifySecurityLevel(const std::string &devId) return DH_SUCCESS; } +void DAudioSinkManager::setNetworkIdSpeakerMap(const std::string &networkId, std::shared_ptr spkClient) +{ + std::lock_guard lock(netwkIdSpeakMapLock_); + netwkIdSpeakMap_[networkId] = spkClient; +} + +void DAudioSinkManager::NotifyWrap(const std::string &devId, const int32_t eventType, const int32_t ret) +{ + cJSON *jParam = cJSON_CreateObject(); + + cJSON_AddStringToObject(jParam, KEY_DH_ID, devId.c_str()); + cJSON_AddNumberToObject(jParam, KEY_RESULT, ret); + char *jsonData = cJSON_PrintUnformatted(jParam); + if (jsonData == nullptr) { + DHLOGE("Failed to create JSON data."); + cJSON_Delete(jParam); + } else { + std::string eventContent = std::string(jsonData); + cJSON_free(jsonData); + cJSON_Delete(jParam); + NotifyEvent(devId, eventType, eventContent); + } +} + +void DAudioSinkManager::CloseAudioWithNetWorkId(const std::string &networkId) +{ + DHLOGI("DAudio allconnect CloseSessionWithNetworkId begin"); + if (networkId.empty()) { + DHLOGE("DAudio allconnect peerNetworkId is empty"); + return; + } + + std::shared_ptr speakerClient = nullptr; + { + std::lock_guard lock(netwkIdSpeakMapLock_); + auto it = netwkIdSpeakMap_.find(networkId); + if (it != netwkIdSpeakMap_.end()) { + speakerClient = it->second; + } + } + + if (speakerClient != nullptr && static_cast(speakerClient.get())->GetTrans() != nullptr) { + CloseSpeakerClient(networkId, speakerClient); + } else { + CloseMicClient(networkId); + } +} + +void DAudioSinkManager::CloseSpeakerClient(const std::string &networkId, std::shared_ptr speakerClient) +{ + int32_t ret = static_cast(speakerClient.get())->GetTrans()->Stop(); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect Stop speaker client failed, ret: %{public}d.", ret); + return; + } + + NotifyWrap(networkId, NOTIFY_CLOSE_SPEAKER_RESULT, ret); + DAudioSinkManager::RemoveSpeakerNetworkId(speakerClient); + ret = DAudioAllConnectManager::GetInstance().PublishServiceState(networkId, SCM_IDLE, SPK_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect CloseSessionWithNetworkId publish service state failed"); + return; + } + DHLOGI("DAudio allconnect Close speaker publish service state idle success"); +} + +void DAudioSinkManager::CloseMicClient(const std::string &networkId) +{ + std::shared_ptr micClient = nullptr; + { + std::lock_guard lock(netwkIdMicMapLock_); + auto it = netwkIdMicMap_.find(networkId); + if (it != netwkIdMicMap_.end()) { + micClient = it->second; + } + } + + int32_t ret = DH_SUCCESS; + if (micClient != nullptr && micClient->GetTrans() != nullptr) { + ret = micClient->GetTrans()->Stop(); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect StopCapture mic client failed, ret: %{public}d.", ret); + return; + } + } + + NotifyWrap(networkId, NOTIFY_CLOSE_MIC_RESULT, ret); + + DAudioSinkManager::RemoveMicNetworkId(micClient); + + ret = DAudioAllConnectManager::GetInstance().PublishServiceState(networkId, SCM_IDLE, MIC_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect mic CloseAudioWithNetWorkId publish service state failed"); + return; + } + DHLOGI("DAudio allconnect Close mic publish service state idle success"); +} + +void DAudioSinkManager::RemoveSpeakerNetworkId(std::shared_ptr spkClient) +{ + std::lock_guard lock(netwkIdSpeakMapLock_); + for (auto it: netwkIdSpeakMap_) { + if (it.second == spkClient) { + netwkIdSpeakMap_.erase(it.first); + break; + } + } +} + +void DAudioSinkManager::SetNetworkIdMicMap(const std::string &networkId, std::shared_ptr micClient) +{ + std::lock_guard lock(netwkIdMicMapLock_); + netwkIdMicMap_[networkId] = micClient; +} + +void DAudioSinkManager::RemoveMicNetworkId(std::shared_ptr micClient) +{ + std::lock_guard lock(netwkIdMicMapLock_); + for (auto it: netwkIdMicMap_) { + if (it.second == micClient) { + netwkIdMicMap_.erase(it.first); + break; + } + } +} + void DeviceInitCallback::OnRemoteDied() { DHLOGI("DeviceInitCallback OnRemoteDied"); diff --git a/services/audiomanager/managersource/include/daudio_io_dev.h b/services/audiomanager/managersource/include/daudio_io_dev.h index 74a4b63a..d9597605 100644 --- a/services/audiomanager/managersource/include/daudio_io_dev.h +++ b/services/audiomanager/managersource/include/daudio_io_dev.h @@ -58,7 +58,9 @@ public: virtual AudioParam GetAudioParam() const = 0; virtual int32_t NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId) = 0; - + virtual int32_t GetPortId() const = 0; + virtual bool IsSpeaker() = 0; + std::string GetDevId() const { return devId_; } protected: const std::string devId_; }; diff --git a/services/audiomanager/managersource/include/daudio_source_dev.h b/services/audiomanager/managersource/include/daudio_source_dev.h index 22c8ebb0..4a711d20 100644 --- a/services/audiomanager/managersource/include/daudio_source_dev.h +++ b/services/audiomanager/managersource/include/daudio_source_dev.h @@ -128,6 +128,8 @@ private: int32_t CreateMicEngine(std::shared_ptr mic); void SetRegDataType(const std::string &capability); void NotifyEventInner(const AudioEvent &event); + int32_t SpeakerAllConnectPublishState(int32_t dhId, std::shared_ptr speaker); + int32_t MicAllConnectPublishState(int32_t dhId, std::shared_ptr mic); private: static constexpr uint8_t RPC_WAIT_SECONDS = 10; diff --git a/services/audiomanager/managersource/include/daudio_source_manager.h b/services/audiomanager/managersource/include/daudio_source_manager.h index c0cf00bf..75e88c75 100644 --- a/services/audiomanager/managersource/include/daudio_source_manager.h +++ b/services/audiomanager/managersource/include/daudio_source_manager.h @@ -54,6 +54,9 @@ public: IAVEngineProvider *getSenderProvider(); IAVEngineProvider *getReceiverProvider(); + static void SetNetworkIdAudioMap(const std::string &networkId, std::shared_ptr ioDev); + void CloseAudioWithNetWorkId(const std::string &networkId); + static void RemoveNetworkId(std::shared_ptr ioDev); private: DAudioSourceManager(); ~DAudioSourceManager(); @@ -65,7 +68,7 @@ private: void RestoreThreadStatus(); int32_t DoEnableDAudio(const std::string &args); int32_t DoDisableDAudio(const std::string &args); - + std::string GenerateEventContent(const std::string &devId, const int32_t eventType); typedef struct { std::string devId; std::shared_ptr dev; @@ -96,17 +99,20 @@ private: void *pRHandler_ = nullptr; std::atomic isHicollieRunning_ = true; + static std::map> netwkIdControlChMap_; + static std::mutex netwkIdControlMapLock_; + class SourceManagerHandler : public AppExecFwk::EventHandler { public: SourceManagerHandler(const std::shared_ptr &runner); ~SourceManagerHandler() override; void ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) override; - + private: void EnableDAudioCallback(const AppExecFwk::InnerEvent::Pointer &event); void DisableDAudioCallback(const AppExecFwk::InnerEvent::Pointer &event); int32_t GetEventParam(const AppExecFwk::InnerEvent::Pointer &event, std::string &eventParam); - + private: using SourceManagerFunc = void (SourceManagerHandler::*)(const AppExecFwk::InnerEvent::Pointer &event); std::map mapEventFuncs_; diff --git a/services/audiomanager/managersource/include/dmic_dev.h b/services/audiomanager/managersource/include/dmic_dev.h index 46a42261..37caeee7 100644 --- a/services/audiomanager/managersource/include/dmic_dev.h +++ b/services/audiomanager/managersource/include/dmic_dev.h @@ -90,7 +90,8 @@ public: int32_t OnStateChange(const AudioEventType type) override; int32_t OnDecodeTransDataDone(const std::shared_ptr &audioData) override; - + int32_t GetPortId() const override; + bool IsSpeaker() override; private: void EnqueueThread(); void FillJitterQueue(); diff --git a/services/audiomanager/managersource/include/dspeaker_dev.h b/services/audiomanager/managersource/include/dspeaker_dev.h index 68d2eaea..6e7da8e6 100644 --- a/services/audiomanager/managersource/include/dspeaker_dev.h +++ b/services/audiomanager/managersource/include/dspeaker_dev.h @@ -66,7 +66,7 @@ public: int32_t ReadMmapPosition(const int32_t streamId, uint64_t &frames, CurrentTimeHDF &time) override; int32_t RefreshAshmemInfo(const int32_t streamId, int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans) override; - + int32_t MmapStart() override; int32_t MmapStop() override; @@ -84,7 +84,8 @@ public: AudioParam GetAudioParam() const override; int32_t NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId) override; - + int32_t GetPortId() const override; + bool IsSpeaker() override; private: void EnqueueThread(); void GetCodecCaps(const std::string &capability); diff --git a/services/audiomanager/managersource/src/daudio_source_dev.cpp b/services/audiomanager/managersource/src/daudio_source_dev.cpp index 1100a753..fbabf39d 100644 --- a/services/audiomanager/managersource/src/daudio_source_dev.cpp +++ b/services/audiomanager/managersource/src/daudio_source_dev.cpp @@ -18,7 +18,6 @@ #include #include "cJSON.h" - #include "daudio_constants.h" #include "daudio_errorcode.h" #include "daudio_hitrace.h" @@ -26,6 +25,7 @@ #include "daudio_radar.h" #include "daudio_source_manager.h" #include "daudio_util.h" +#include "distributed_audio_allconnect_manager.h" #undef DH_LOG_TAG #define DH_LOG_TAG "DAudioSourceDev" @@ -934,10 +934,9 @@ int32_t DAudioSourceDev::TaskOpenDSpeaker(const std::string &args) NotifyHDF(NOTIFY_OPEN_SPEAKER_RESULT, HDF_EVENT_RESULT_FAILED, dhId); return ERR_DH_AUDIO_NULLPTR; } - int32_t ret = CreateSpkEngine(speaker); + + int32_t ret = SpeakerAllConnectPublishState(dhId, speaker); if (ret != DH_SUCCESS) { - DHLOGE("Create speaker engine failed."); - NotifyHDF(NOTIFY_OPEN_SPEAKER_RESULT, HDF_EVENT_INIT_ENGINE_FAILED, dhId); return ret; } cJSON *jAudioParam = cJSON_CreateObject(); @@ -962,6 +961,41 @@ int32_t DAudioSourceDev::TaskOpenDSpeaker(const std::string &args) return DH_SUCCESS; } +int32_t DAudioSourceDev::SpeakerAllConnectPublishState(int32_t dhId, std::shared_ptr speaker) +{ + auto resourceReq = DAudioAllConnectManager::GetInstance().BuildResourceRequest(true); + int32_t ret = DAudioAllConnectManager::GetInstance().ApplyAdvancedResource(devId_, resourceReq.get(), + SPK_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect speaker apply advanced resource failed, ret: %{public}d, devId: %{public}s", + ret, GetAnonyString(devId_).c_str()); + return ret; + } + ret = DAudioAllConnectManager::GetInstance().PublishServiceState(devId_, SCM_PREPARE, SPK_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect speaker publish scm prepare failed, ret: %{public}d, devId: %{public}s", + ret, GetAnonyString(devId_).c_str()); + return ret; + } + DHLOGI("DAudio allconnect speaker apply advanced resource publish scm prepare success"); + + ret = CreateSpkEngine(speaker); + if (ret != DH_SUCCESS) { + DHLOGE("Create speaker engine failed."); + NotifyHDF(NOTIFY_OPEN_SPEAKER_RESULT, HDF_EVENT_INIT_ENGINE_FAILED, dhId); + return ret; + } + + ret = DAudioAllConnectManager::GetInstance().PublishServiceState(devId_, SCM_CONNECTED, SPK_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect speaker publish scm connected failed, ret: %{public}d", ret); + } else { + DHLOGI("DAudio allconnect create speaker engine publish scm connected success"); + } + DAudioSourceManager::SetNetworkIdAudioMap(devId_, speaker); + return ret; +} + int32_t DAudioSourceDev::ParseDhidFromEvent(std::string args) { cJSON *jParam = cJSON_Parse(args.c_str()); @@ -1037,6 +1071,8 @@ int32_t DAudioSourceDev::CloseSpkNew(const std::string &args) if (!closeStatus) { return ERR_DH_AUDIO_FAILED; } + DAudioSourceManager::RemoveNetworkId(speaker); + return DH_SUCCESS; } @@ -1067,9 +1103,18 @@ int32_t DAudioSourceDev::TaskCloseDSpeaker(const std::string &args) NotifyHDF(NOTIFY_CLOSE_SPEAKER_RESULT, HDF_EVENT_RESULT_FAILED, dhId); return ret; } + + ret = DAudioAllConnectManager::GetInstance().PublishServiceState(devId_, SCM_IDLE, SPK_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect source speaker publish SCM_IDLE failed, ret: %{public}d, devId: %{public}s ", + ret, GetAnonyString(devId_).c_str()); + } else { + DHLOGI("DAudio allconnect close speaker publish scm idle success"); + } + NotifyHDF(NOTIFY_CLOSE_SPEAKER_RESULT, HDF_EVENT_RESULT_SUCCESS, dhId); NotifyFwkIdle(devId_, std::to_string(dhId)); - return DH_SUCCESS; + return ret; } int32_t DAudioSourceDev::CreateMicEngine(std::shared_ptr mic) @@ -1118,10 +1163,9 @@ int32_t DAudioSourceDev::TaskOpenDMic(const std::string &args) NotifyHDF(NOTIFY_OPEN_MIC_RESULT, HDF_EVENT_RESULT_FAILED, dhId); return ERR_DH_AUDIO_NULLPTR; } - int32_t ret = CreateMicEngine(mic); + + int32_t ret = MicAllConnectPublishState(dhId, mic); if (ret != DH_SUCCESS) { - DHLOGE("Create mic engine failed."); - NotifyHDF(NOTIFY_OPEN_MIC_RESULT, HDF_EVENT_INIT_ENGINE_FAILED, dhId); return ret; } cJSON *jAudioParam = cJSON_CreateObject(); @@ -1152,6 +1196,42 @@ int32_t DAudioSourceDev::TaskOpenDMic(const std::string &args) return DH_SUCCESS; } +int32_t DAudioSourceDev::MicAllConnectPublishState(int32_t dhId, std::shared_ptr mic) +{ + auto resourceReq = DAudioAllConnectManager::GetInstance().BuildResourceRequest(false); + int32_t ret = DAudioAllConnectManager::GetInstance().ApplyAdvancedResource(devId_, resourceReq.get(), + MIC_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect mic apply advanced resource failed, ret: %{public}d, devId: %{public}s", + ret, GetAnonyString(devId_).c_str()); + return ret; + } + ret = DAudioAllConnectManager::GetInstance().PublishServiceState(devId_, SCM_PREPARE, MIC_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect mic publish scm prepare failed, ret: %{public}d, devId: %{public}s", + ret, GetAnonyString(devId_).c_str()); + return ret; + } + + DHLOGI("DAudio allconnect mic apply advanced resource publish scm prepare success"); + + ret = CreateMicEngine(mic); + if (ret != DH_SUCCESS) { + DHLOGE("Create mic engine failed."); + NotifyHDF(NOTIFY_OPEN_MIC_RESULT, HDF_EVENT_INIT_ENGINE_FAILED, dhId); + return ret; + } + + ret = DAudioAllConnectManager::GetInstance().PublishServiceState(devId_, SCM_CONNECTED, MIC_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect mic publish scm connected failed, ret: %{public}d", ret); + } else { + DHLOGI("DAudio allconnect create mic engine publish scm connected success"); + } + DAudioSourceManager::SetNetworkIdAudioMap(devId_, mic); + return ret; +} + int32_t DAudioSourceDev::CloseMicNew(const std::string &args) { DHLOGI("Close mic new."); @@ -1166,6 +1246,7 @@ int32_t DAudioSourceDev::CloseMicNew(const std::string &args) if (mic->Stop() != DH_SUCCESS || mic->Release() != DH_SUCCESS) { return ERR_DH_AUDIO_FAILED; } + DAudioSourceManager::RemoveNetworkId(mic); return DH_SUCCESS; } @@ -1195,9 +1276,18 @@ int32_t DAudioSourceDev::TaskCloseDMic(const std::string &args) NotifyHDF(NOTIFY_CLOSE_MIC_RESULT, HDF_EVENT_RESULT_FAILED, dhId); return ret; } + + ret = DAudioAllConnectManager::GetInstance().PublishServiceState(devId_, SCM_IDLE, MIC_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect source mic publish SCM_IDLE failed, ret: %{public}d, devId: %{public}s ", + ret, GetAnonyString(devId_).c_str()); + } else { + DHLOGI("DAudio allconnect close mic publish scm idle success"); + } + NotifyHDF(NOTIFY_CLOSE_MIC_RESULT, HDF_EVENT_RESULT_SUCCESS, dhId); NotifyFwkIdle(devId_, std::to_string(dhId)); - return DH_SUCCESS; + return ret; } int32_t DAudioSourceDev::TaskDMicClosed(const std::string &args) diff --git a/services/audiomanager/managersource/src/daudio_source_manager.cpp b/services/audiomanager/managersource/src/daudio_source_manager.cpp index 9177d2bb..2d79b163 100644 --- a/services/audiomanager/managersource/src/daudio_source_manager.cpp +++ b/services/audiomanager/managersource/src/daudio_source_manager.cpp @@ -25,6 +25,7 @@ #include "daudio_log.h" #include "daudio_util.h" #include "daudio_radar.h" +#include "distributed_audio_allconnect_manager.h" #undef DH_LOG_TAG #define DH_LOG_TAG "DAudioSourceManager" @@ -64,6 +65,9 @@ DAudioSourceManager::~DAudioSourceManager() DHLOGD("Distributed audio source manager destructed."); } +std::map> DAudioSourceManager::netwkIdControlChMap_; +std::mutex DAudioSourceManager::netwkIdControlMapLock_; + int32_t DAudioSourceManager::Init(const sptr &callback) { DHLOGI("Init audio source manager."); @@ -578,6 +582,92 @@ IAVEngineProvider *DAudioSourceManager::getReceiverProvider() return rcvProviderPtr_; } +void DAudioSourceManager::SetNetworkIdAudioMap(const std::string &networkId, std::shared_ptr ioDev) +{ + std::lock_guard lock(netwkIdControlMapLock_); + netwkIdControlChMap_[networkId] = ioDev; +} + +std::string DAudioSourceManager::GenerateEventContent(const std::string &devId, const int32_t eventType) +{ + cJSON *jParam = cJSON_CreateObject(); + cJSON_AddStringToObject(jParam, KEY_DH_ID, devId.c_str()); + char *jsonData = cJSON_PrintUnformatted(jParam); + if (jsonData == nullptr) { + DHLOGE("Failed to create JSON data."); + cJSON_Delete(jParam); + return ""; + } + std::string eventContent = std::string(jsonData); + cJSON_free(jsonData); + cJSON_Delete(jParam); + return eventContent; +} + +void DAudioSourceManager::CloseAudioWithNetWorkId(const std::string &networkId) +{ + DHLOGI("DAudio allconnect CloseSessionWithNetworkId begin"); + if (networkId.empty()) { + DHLOGE("DAudio allconnect peerNetworkId is empty"); + return; + } + + std::shared_ptr audio = nullptr; + { + std::lock_guard lock(netwkIdControlMapLock_); + auto it = netwkIdControlChMap_.find(networkId); + if (it != netwkIdControlChMap_.end()) { + audio = it->second; + } + } + + if (audio != nullptr) { + int32_t ret = audio->Stop(); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect CloseAudioWithNetWorkId stop failed"); + } + + ret = audio->Release(); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect CloseAudioWithNetWorkId release failed"); + } + DAudioSourceManager::RemoveNetworkId(audio); + + std::string serviceName; + if (audio->IsSpeaker()) { + AudioEvent audioEvent(AUDIO_EVENT_SPK_CONFLICT, + GenerateEventContent(audio->GetDevId(), AUDIO_EVENT_SPK_CONFLICT)); + audio->NotifyHdfAudioEvent(audioEvent, audio->GetPortId()); + serviceName = SPK_SERVICE_NAME; + } else { + AudioEvent audioEvent(AUDIO_EVENT_MIC_CONFLICT, + GenerateEventContent(audio->GetDevId(), AUDIO_EVENT_MIC_CONFLICT)); + audio->NotifyHdfAudioEvent(audioEvent, audio->GetPortId()); + serviceName = MIC_SERVICE_NAME; + } + + ret = DAudioAllConnectManager::GetInstance().PublishServiceState(networkId, SCM_IDLE, serviceName); + if (ret != DH_SUCCESS) { + DHLOGE("DAudio allconnect CloseAudio publish service state failed"); + } else { + DHLOGI("DAudio allconnect CloseAudio publish service state idle success"); + } + } else { + DHLOGI("DAudio allconnect CloseSessionWithNetworkId audio is null"); + } +} + +void DAudioSourceManager::RemoveNetworkId(std::shared_ptr ioDev) +{ + std::lock_guard lock(netwkIdControlMapLock_); + for (auto it: netwkIdControlChMap_) { + if (it.second == ioDev) { + netwkIdControlChMap_.erase(it.first); + break; + } + } +} + DAudioSourceManager::SourceManagerHandler::SourceManagerHandler(const std::shared_ptr &runner) : AppExecFwk::EventHandler(runner) { diff --git a/services/audiomanager/managersource/src/dmic_dev.cpp b/services/audiomanager/managersource/src/dmic_dev.cpp index a1cbbfc8..5db8d888 100644 --- a/services/audiomanager/managersource/src/dmic_dev.cpp +++ b/services/audiomanager/managersource/src/dmic_dev.cpp @@ -457,6 +457,7 @@ int32_t DMicDev::Release() DHLOGE("Release mic trans failed, ret: %{public}d.", ret); return ret; } + isRingbufferOn_.store(false); if (ringbufferThread_.joinable()) { ringbufferThread_.join(); @@ -649,7 +650,14 @@ AudioParam DMicDev::GetAudioParam() const { return param_; } - +int32_t DMicDev::GetPortId() const +{ + return curPort_; +} +bool DMicDev::IsSpeaker() +{ + return false; +} int32_t DMicDev::NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId) { int32_t ret = DAudioHdiHandler::GetInstance().NotifyEvent(devId_, portId, streamId_, event); diff --git a/services/audiomanager/managersource/src/dspeaker_dev.cpp b/services/audiomanager/managersource/src/dspeaker_dev.cpp index 18ee5172..e81b6529 100644 --- a/services/audiomanager/managersource/src/dspeaker_dev.cpp +++ b/services/audiomanager/managersource/src/dspeaker_dev.cpp @@ -196,7 +196,14 @@ int32_t DSpeakerDev::CreateStream(const int32_t streamId) BizState::BIZ_STATE_START, DH_SUCCESS); return DH_SUCCESS; } - +int32_t DSpeakerDev::GetPortId() const +{ + return curPort_; +} +bool DSpeakerDev::IsSpeaker() +{ + return true; +} int32_t DSpeakerDev::DestroyStream(const int32_t streamId) { DHLOGI("Close stream of speaker device streamId: %{public}d.", streamId); @@ -332,6 +339,7 @@ int32_t DSpeakerDev::Release() if (ret != DH_SUCCESS) { DHLOGE("Release speaker trans failed, ret: %{public}d.", ret); } + DumpFileUtil::CloseDumpFile(&dumpFileCommn_); DumpFileUtil::CloseDumpFile(&dumpFileFast_); return DH_SUCCESS; diff --git a/services/audiomanager/servicesink/BUILD.gn b/services/audiomanager/servicesink/BUILD.gn index cd83fc45..1b80fd26 100755 --- a/services/audiomanager/servicesink/BUILD.gn +++ b/services/audiomanager/servicesink/BUILD.gn @@ -42,7 +42,9 @@ ohos_shared_library("distributed_audio_sink") { "${common_path}/include", "${innerkits_path}/native_cpp/audio_sink/include", "${innerkits_path}/native_cpp/audio_source/include", + "${services_path}/audiomanager/allconnect/include", "${services_path}/audiomanager/managersink/include", + "${services_path}/audiomanager/managersource/include", "${services_path}/common/audioeventcallback", "${services_path}/common/audiodata/include", "${services_path}/common/audioparam", @@ -58,6 +60,7 @@ ohos_shared_library("distributed_audio_sink") { "${innerkits_path}/native_cpp/audio_sink/src/daudio_sink_load_callback.cpp", "${innerkits_path}/native_cpp/audio_sink/src/daudio_sink_proxy.cpp", "${innerkits_path}/native_cpp/audio_source/src/daudio_source_proxy.cpp", + "${services_path}/audiomanager/allconnect/src/distributed_audio_allconnect_manager.cpp", "${services_path}/audiomanager/managersink/src/daudio_sink_dev.cpp", "${services_path}/audiomanager/managersink/src/daudio_sink_manager.cpp", "src/daudio_sink_hidumper.cpp", @@ -104,6 +107,8 @@ ohos_shared_library("distributed_audio_sink") { "samgr:samgr_proxy", ] + cflags = [ "-DAUDIO_ALLCONNECT_SINK" ] + defines = [ "HI_LOG_ENABLE", "LOG_DOMAIN=0xD004130", diff --git a/services/audiomanager/servicesink/src/daudio_sink_service.cpp b/services/audiomanager/servicesink/src/daudio_sink_service.cpp index aecd1be2..06029bcf 100644 --- a/services/audiomanager/servicesink/src/daudio_sink_service.cpp +++ b/services/audiomanager/servicesink/src/daudio_sink_service.cpp @@ -28,6 +28,7 @@ #include "daudio_log.h" #include "daudio_sink_manager.h" #include "daudio_util.h" +#include "distributed_audio_allconnect_manager.h" #undef DH_LOG_TAG #define DH_LOG_TAG "DAudioSinkService" @@ -48,13 +49,42 @@ void DAudioSinkService::OnStart() DHLOGE("Init service failed."); return; } - DHLOGD("Start distributed audio service success."); + int32_t ret = DAudioAllConnectManager::GetInstance().InitDAudioAllConnectManager(SPK_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGI("DAudio allconnect source speaker register lifecyle failed"); + } else { + DHLOGI("DAudio allconnect source speaker register lifecyle success"); + } + + ret = DAudioAllConnectManager::GetInstance().InitDAudioAllConnectManager(MIC_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGI("DAudio allconnect source mic register lifecyle failed"); + } else { + DHLOGI("DAudio allconnect source mic register lifecyle success"); + } + + DHLOGD("Start daudio sink service end."); } void DAudioSinkService::OnStop() { DHLOGI("Distributed audio service on stop."); isServiceStarted_ = false; + int32_t ret = DAudioAllConnectManager::GetInstance().UnInitDAudioAllConnectManager(SPK_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGI("DAudio allconnect source speaker UnRegister lifecyle failed"); + } else { + DHLOGI("DAudio allconnect source speaker UnRegister lifecyle success"); + } + + ret = DAudioAllConnectManager::GetInstance().UnInitDAudioAllConnectManager(MIC_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGI("DAudio allconnect source mic UnRegister lifecyle failed"); + } else { + DHLOGI("DAudio allconnect source mic UnRegister lifecyle success"); + } + + DHLOGD("stop daudio sink service end."); } bool DAudioSinkService::Init() diff --git a/services/audiomanager/servicesource/BUILD.gn b/services/audiomanager/servicesource/BUILD.gn index 0c760dee..f06f9cab 100755 --- a/services/audiomanager/servicesource/BUILD.gn +++ b/services/audiomanager/servicesource/BUILD.gn @@ -26,9 +26,9 @@ ohos_shared_library("distributed_audio_source") { ubsan = true } stack_protector_ret = true - include_dirs = [ "include", + "${audio_client_path}/interface", "${audio_client_path}/micclient/include", "${audio_client_path}/spkclient/include", "${audio_control_path}/controlsource/include", @@ -45,6 +45,7 @@ ohos_shared_library("distributed_audio_source") { "${innerkits_path}/native_cpp/audio_source/include", "${interfaces_path}/inner_kits/native_cpp/audio_sink/include", "${interfaces_path}/inner_kits/native_cpp/audio_source/include", + "${services_path}/audiomanager/allconnect/include", "${services_path}/audiomanager/managersource/include", "${services_path}/common/audiodata/include", "${services_path}/common/audioeventcallback", @@ -71,6 +72,7 @@ ohos_shared_library("distributed_audio_source") { "${common_path}/dfx_utils/src/daudio_hidumper.cpp", "${interfaces_path}/inner_kits/native_cpp/audio_sink/src/daudio_sink_proxy.cpp", "${interfaces_path}/inner_kits/native_cpp/audio_source/src/daudio_source_proxy.cpp", + "${services_path}/audiomanager/allconnect/src/distributed_audio_allconnect_manager.cpp", "${services_path}/audiomanager/managersource/src/daudio_source_dev.cpp", "${services_path}/audiomanager/managersource/src/daudio_source_manager.cpp", "${services_path}/audiomanager/managersource/src/daudio_source_mgr_callback.cpp", @@ -128,6 +130,8 @@ ohos_shared_library("distributed_audio_source") { cflags += [ "-DAUDIO_SUPPORT_SHARED_BUFFER" ] } + cflags += [ "-DAUDIO_ALLCONNECT_SOURCE" ] + cflags_cc = cflags ldflags = [ diff --git a/services/audiomanager/servicesource/src/daudio_source_service.cpp b/services/audiomanager/servicesource/src/daudio_source_service.cpp index 5f5bde03..4c816065 100644 --- a/services/audiomanager/servicesource/src/daudio_source_service.cpp +++ b/services/audiomanager/servicesource/src/daudio_source_service.cpp @@ -29,6 +29,7 @@ #include "daudio_radar.h" #include "daudio_source_manager.h" #include "daudio_util.h" +#include "distributed_audio_allconnect_manager.h" #undef DH_LOG_TAG #define DH_LOG_TAG "DAudioSourceService" @@ -43,13 +44,50 @@ void DAudioSourceService::OnStart() DHLOGE("Init service failed."); return; } - DHLOGI("Start distributed audio service success."); + int32_t ret = DH_SUCCESS; + if (!DAudioAllConnectManager::IsSpkInited()) { + ret = DAudioAllConnectManager::GetInstance().InitDAudioAllConnectManager(SPK_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGI("DAudio allconnect source speaker register lifecyle failed"); + } else { + DHLOGI("DAudio allconnect source speaker register lifecyle success"); + } + } + + if (!DAudioAllConnectManager::IsMicInited()) { + ret = DAudioAllConnectManager::GetInstance().InitDAudioAllConnectManager(MIC_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGI("DAudio allconnect source mic register lifecyle failed"); + } else { + DHLOGI("DAudio allconnect source mic register lifecyle success"); + } + } + DHLOGD("start daudio source service end."); } void DAudioSourceService::OnStop() { DHLOGI("Distributed audio service on stop."); isServiceStarted_ = false; + int32_t ret = DH_SUCCESS; + if (DAudioAllConnectManager::IsSpkInited()) { + ret = DAudioAllConnectManager::GetInstance().UnInitDAudioAllConnectManager(SPK_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGI("DAudio allconnect source speaker UnRegister lifecyle failed"); + } else { + DHLOGI("DAudio allconnect source speaker UnRegister lifecyle success"); + } + } + + if (DAudioAllConnectManager::IsMicInited()) { + ret = DAudioAllConnectManager::GetInstance().UnInitDAudioAllConnectManager(MIC_SERVICE_NAME); + if (ret != DH_SUCCESS) { + DHLOGI("DAudio allconnect source mic UnRegister lifecyle failed"); + } else { + DHLOGI("DAudio allconnect source mic UnRegister lifecyle success"); + } + } + DHLOGD("stop daudio source service end."); } bool DAudioSourceService::Init() diff --git a/services/common/audioparam/audio_event.h b/services/common/audioparam/audio_event.h index 469f14dc..16060566 100644 --- a/services/common/audioparam/audio_event.h +++ b/services/common/audioparam/audio_event.h @@ -97,6 +97,8 @@ typedef enum { AUDIO_EVENT_STOP = 19, AUDIO_EVENT_SPK_DUMP = 20, AUDIO_EVENT_MIC_DUMP = 21, + AUDIO_EVENT_SPK_CONFLICT = 22, + AUDIO_EVENT_MIC_CONFLICT = 23, } AudioEventHDF; class AudioEvent { public: -- Gitee