diff --git a/services/audiomanager/managersink/include/daudio_sink_dev.h b/services/audiomanager/managersink/include/daudio_sink_dev.h index 856736cb51a22e2797f3fd917ef0f5808b2e056c..2616ff769c19ced41c4439438379f0a95103d8a3 100644 --- a/services/audiomanager/managersink/include/daudio_sink_dev.h +++ b/services/audiomanager/managersink/include/daudio_sink_dev.h @@ -16,6 +16,7 @@ #ifndef OHOS_DAUDIO_SINK_DEV_H #define OHOS_DAUDIO_SINK_DEV_H +#include #include #include #include @@ -40,6 +41,12 @@ using json = nlohmann::json; namespace OHOS { namespace DistributedHardware { +enum class ChannelState { + SPK_CONTROL_OPENED, + MIC_CONTROL_OPENED, + UNKNOWN, +}; + class DAudioSinkDev : public IAudioEventCallback, public std::enable_shared_from_this { public: explicit DAudioSinkDev(const std::string &networkId); @@ -48,7 +55,7 @@ public: int32_t AwakeAudioDev(); void SleepAudioDev(); void NotifyEvent(const AudioEvent &audioEvent) override; - int32_t InitAVTransEngines(IAVEngineProvider *senderPtr, IAVEngineProvider *receiverPtr); + int32_t InitAVTransEngines(const ChannelState channelState, IAVEngineProvider *providerPtr); private: int32_t TaskOpenCtrlChannel(const std::string &args); @@ -89,6 +96,7 @@ private: int32_t from_json(const json &j, AudioParam &audioParam); int32_t HandleEngineMessage(uint32_t type, std::string content, std::string devId); int32_t SendAudioEventToRemote(const AudioEvent &event); + void JudgeDeviceStatus(); private: std::mutex taskQueueMutex_; @@ -105,6 +113,8 @@ private: using DAudioSinkDevFunc = int32_t (DAudioSinkDev::*)(const AudioEvent &audioEvent); std::map memberFuncMap_; bool engineFlag_ = false; + std::atomic isSpkInUse_ = false; + std::atomic isMicInUse_ = false; }; } // DistributedHardware } // OHOS diff --git a/services/audiomanager/managersink/include/daudio_sink_manager.h b/services/audiomanager/managersink/include/daudio_sink_manager.h index 4b1df962a506c553ba2608241f611d0defb8481f..1b6b6f88f1368ef3e83b635645d499572dea53c0 100644 --- a/services/audiomanager/managersink/include/daudio_sink_manager.h +++ b/services/audiomanager/managersink/include/daudio_sink_manager.h @@ -48,6 +48,8 @@ public: void NotifyEvent(const std::string &devId, const int32_t eventType, const std::string &eventContent); void ClearAudioDev(const std::string &devId); int32_t CreateAudioDevice(const std::string &devId); + void SetChannelState(const std::string &content); + private: DAudioSinkManager(); ~DAudioSinkManager(); @@ -64,6 +66,7 @@ private: std::map> sourceServiceMap_; std::thread devClearThread_; std::string localNetworkId_; + ChannelState channelState_ = ChannelState::UNKNOWN; std::shared_ptr providerListener_; IAVEngineProvider *sendProviderPtr_ = nullptr; diff --git a/services/audiomanager/managersink/src/daudio_sink_dev.cpp b/services/audiomanager/managersink/src/daudio_sink_dev.cpp index 8400fab3c1c34b6ca5d6122bfc26bfbfa23349ec..4e8831ca1cfa2f9f43370633b0273baca5ae662b 100644 --- a/services/audiomanager/managersink/src/daudio_sink_dev.cpp +++ b/services/audiomanager/managersink/src/daudio_sink_dev.cpp @@ -78,18 +78,22 @@ void DAudioSinkDev::SleepAudioDev() taskQueue_ = nullptr; } -int32_t DAudioSinkDev::InitAVTransEngines(IAVEngineProvider *senderPtr, IAVEngineProvider *receiverPtr) +int32_t DAudioSinkDev::InitAVTransEngines(const ChannelState channelState, IAVEngineProvider *providerPtr) { DHLOGI("Init InitAVTransEngines"); - if (engineFlag_) { + if (channelState == ChannelState::UNKNOWN || providerPtr == nullptr) { + DHLOGE("The channel type is invalid."); + return ERR_DH_AUDIO_FAILED; + } + if (engineFlag_ && channelState == ChannelState::MIC_CONTROL_OPENED) { // only supports normal audio channel mode micClient_ = std::make_shared(devId_, shared_from_this()); - micClient_->InitSenderEngine(senderPtr); + micClient_->InitSenderEngine(providerPtr); } - if (engineFlag_) { + if (engineFlag_ && channelState == ChannelState::SPK_CONTROL_OPENED) { speakerClient_ = std::make_shared(devId_, shared_from_this()); - speakerClient_->InitReceiverEngine(receiverPtr); + speakerClient_->InitReceiverEngine(providerPtr); } return DH_SUCCESS; } @@ -440,6 +444,7 @@ int32_t DAudioSinkDev::TaskOpenDSpeaker(const std::string &args) NotifySourceDev(NOTIFY_OPEN_SPEAKER_RESULT, spkDhId_, ret); DHLOGI("Open speaker device task end, notify source ret %d.", ret); + isSpkInUse_.store(true); return ret; } @@ -471,6 +476,10 @@ int32_t DAudioSinkDev::TaskCloseDSpeaker(const std::string &args) closeStatus ? NotifySourceDev(NOTIFY_CLOSE_SPEAKER_RESULT, spkDhId_, DH_SUCCESS) : NotifySourceDev(NOTIFY_CLOSE_SPEAKER_RESULT, spkDhId_, ERR_DH_AUDIO_FAILED); } + isSpkInUse_.store(false); + if (engineFlag_) { + JudgeDeviceStatus(); + } DHLOGI("Close speaker device task excute success."); return DH_SUCCESS; } @@ -524,6 +533,7 @@ int32_t DAudioSinkDev::TaskOpenDMic(const std::string &args) } while (false); NotifySourceDev(NOTIFY_OPEN_MIC_RESULT, micDhId_, ret); DHLOGI("Open mic device task end, notify source ret %d.", ret); + isMicInUse_.store(true); return ret; } @@ -555,6 +565,10 @@ int32_t DAudioSinkDev::TaskCloseDMic(const std::string &args) closeStatus ? NotifySourceDev(NOTIFY_CLOSE_MIC_RESULT, micDhId_, DH_SUCCESS) : NotifySourceDev(NOTIFY_CLOSE_MIC_RESULT, micDhId_, ERR_DH_AUDIO_FAILED); } + isMicInUse_.store(false); + if (engineFlag_) { + JudgeDeviceStatus(); + } DHLOGI("Close mic device task excute success."); return DH_SUCCESS; } @@ -666,6 +680,17 @@ int32_t DAudioSinkDev::SendAudioEventToRemote(const AudioEvent &event) return DH_SUCCESS; } +void DAudioSinkDev::JudgeDeviceStatus() +{ + DHLOGI("Checking device's status."); + if (isSpkInUse_.load() || isMicInUse_.load()) { + DHLOGI("Device contain periperials in using, speaker status: %d, mic status: %d.", + isSpkInUse_.load(), isMicInUse_.load()); + return; + } + DAudioSinkManager::GetInstance().OnSinkDevReleased(devId_); +} + void DAudioSinkDev::OnTaskResult(int32_t resultCode, const std::string &result, const std::string &funcName) { (void)resultCode; @@ -689,16 +714,16 @@ void DAudioSinkDev::NotifySourceDev(const AudioEventType type, const std::string DAudioSinkManager::GetInstance().DAudioNotify(devId_, dhId, type, jEvent.dump()); } else { DHLOGD("Notify source dev, new engine, random task code:%s", std::to_string(randomTaskCode).c_str()); - if (speakerClient_ == nullptr || micClient_ == nullptr) { - DHLOGE("speaker client or mic client is null."); - return; - } if (type == NOTIFY_OPEN_CTRL_RESULT || type == NOTIFY_CLOSE_CTRL_RESULT) { DHLOGE("In new engine mode, ctrl is not allowed."); return; } - speakerClient_->SendMessage(static_cast(type), jEvent.dump(), devId_); - micClient_->SendMessage(static_cast(type), jEvent.dump(), devId_); + if (speakerClient_ != nullptr) { + speakerClient_->SendMessage(static_cast(type), jEvent.dump(), devId_); + } + if (micClient_ != nullptr) { + micClient_->SendMessage(static_cast(type), jEvent.dump(), devId_); + } } } diff --git a/services/audiomanager/managersink/src/daudio_sink_manager.cpp b/services/audiomanager/managersink/src/daudio_sink_manager.cpp index fb55364cba232b26d3676959badeaf29b53db9b5..fa17858c70ab401b35d9151d3b68d532c67ab515 100644 --- a/services/audiomanager/managersink/src/daudio_sink_manager.cpp +++ b/services/audiomanager/managersink/src/daudio_sink_manager.cpp @@ -29,6 +29,11 @@ namespace OHOS { namespace DistributedHardware { +static const std::string PARAM_CLOSE_SPEAKER = "{\"audioParam\":null,\"dhId\":\"" + + std::to_string(PIN_OUT_SPEAKER) + "\",\"eventType\":12}"; +static const std::string PARAM_CLOSE_MIC = "{\"audioParam\":null,\"dhId\":\"" + + std::to_string(PIN_IN_MIC) + "\",\"eventType\":22}"; + IMPLEMENT_SINGLE_INSTANCE(DAudioSinkManager); using AVTransProviderClass = IAVEngineProvider *(*)(const std::string &); @@ -161,26 +166,40 @@ int32_t DAudioSinkManager::HandleDAudioNotify(const std::string &devId, const st int32_t DAudioSinkManager::CreateAudioDevice(const std::string &devId) { DHLOGI("Create audio sink dev."); - if (engineFlag_) { + std::shared_ptr dev = nullptr; + { std::lock_guard lock(devMapMutex_); if (audioDevMap_.find(devId) != audioDevMap_.end()) { DHLOGI("Audio sink dev in map. devId: %s.", GetAnonyString(devId).c_str()); - return DH_SUCCESS; + dev = audioDevMap_[devId]; + } else { + dev = std::make_shared(devId); + if (dev->AwakeAudioDev() != DH_SUCCESS) { + DHLOGE("Awake audio dev failed."); + return ERR_DH_AUDIO_FAILED; + } + audioDevMap_.emplace(devId, dev); } } - auto dev = std::make_shared(devId); - if (dev->AwakeAudioDev() != DH_SUCCESS) { - DHLOGE("Awake audio dev failed."); - return ERR_DH_AUDIO_FAILED; - } + if (engineFlag_) { - int32_t ret = dev->InitAVTransEngines(sendProviderPtr_, rcvProviderPtr_); + int32_t ret = ERR_DH_AUDIO_FAILED; + if (channelState_ == ChannelState::SPK_CONTROL_OPENED) { + ret = dev->InitAVTransEngines(ChannelState::SPK_CONTROL_OPENED, rcvProviderPtr_); + } + if (channelState_ == ChannelState::MIC_CONTROL_OPENED) { + ret = dev->InitAVTransEngines(ChannelState::MIC_CONTROL_OPENED, sendProviderPtr_); + } if (ret != DH_SUCCESS) { DHLOGE("Init av transport sender engine failed."); + dev->SleepAudioDev(); + { + std::lock_guard lock(devMapMutex_); + audioDevMap_.erase(devId); + } return ERR_DH_AUDIO_FAILED; } } - audioDevMap_.emplace(devId, dev); return DH_SUCCESS; } @@ -319,21 +338,40 @@ int32_t DAudioSinkManager::UnloadAVSenderEngineProvider() return DH_SUCCESS; } +void DAudioSinkManager::SetChannelState(const std::string &content) +{ + DHLOGI("The channel state belong to %s.", content.c_str()); + if (content.find(OWNER_NAME_D_SPEAKER) != content.npos) { + channelState_ = ChannelState::SPK_CONTROL_OPENED; + } else if (content.find(OWNER_NAME_D_MIC) != content.npos) { + channelState_ = ChannelState::MIC_CONTROL_OPENED; + } +} + int32_t EngineProviderListener::OnProviderEvent(const AVTransEvent &event) { DHLOGI("On provider event :%d", event.type); if (event.type == EventType::EVENT_CHANNEL_OPENED) { - DHLOGI("Received control channel opened event, create audio device for peerDevId=%s", - GetAnonyString(event.peerDevId).c_str()); + DHLOGI("Received control channel opened event, create audio device for peerDevId=%s, content=%s.", + GetAnonyString(event.peerDevId).c_str(), event.content.c_str()); + DAudioSinkManager::GetInstance().SetChannelState(event.content); DAudioSinkManager::GetInstance().CreateAudioDevice(event.peerDevId); } else if (event.type == EventType::EVENT_CHANNEL_CLOSED) { DHLOGI("Received control channel closed event, clear audio device for peerDevId=%s", GetAnonyString(event.peerDevId).c_str()); - DAudioSinkManager::GetInstance().ClearAudioDev(event.peerDevId); + if (event.content.find(OWNER_NAME_D_SPEAKER) != event.content.npos) { + DHLOGD("Notify audio event, event type: %d, event content: %s.", CLOSE_SPEAKER, + PARAM_CLOSE_SPEAKER.c_str()); + DAudioSinkManager::GetInstance().NotifyEvent(event.peerDevId, CLOSE_SPEAKER, PARAM_CLOSE_SPEAKER); + } + if (event.content.find(OWNER_NAME_D_MIC) != event.content.npos) { + DHLOGD("Notify audio event, event type: %d, event content: %s.", CLOSE_MIC, PARAM_CLOSE_MIC.c_str()); + DAudioSinkManager::GetInstance().NotifyEvent(event.peerDevId, CLOSE_MIC, PARAM_CLOSE_MIC); + } } else { DHLOGE("Invaild event type."); } return DH_SUCCESS; } } // namespace DistributedHardware -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/services/audiomanager/test/unittest/managersink/src/daudio_sink_dev_test.cpp b/services/audiomanager/test/unittest/managersink/src/daudio_sink_dev_test.cpp index b2e4f115d91415872394d486d1e5bded7809ac79..186c96a640bf7a823d0be787fe4a44bb0eeee075 100644 --- a/services/audiomanager/test/unittest/managersink/src/daudio_sink_dev_test.cpp +++ b/services/audiomanager/test/unittest/managersink/src/daudio_sink_dev_test.cpp @@ -48,8 +48,14 @@ HWTEST_F(DAudioSinkDevTest, InitAVTransEngines_001, TestSize.Level1) { IAVEngineProvider *senderPtr = nullptr; IAVEngineProvider *receiverPtr = nullptr; + ChannelState type = ChannelState::UNKNOWN; sinkDev_->engineFlag_ = true; - EXPECT_EQ(DH_SUCCESS, sinkDev_->InitAVTransEngines(senderPtr, receiverPtr)); + + EXPECT_EQ(ERR_DH_AUDIO_FAILED, sinkDev_->InitAVTransEngines(type, receiverPtr)); + type = ChannelState::MIC_CONTROL_OPENED; + EXPECT_EQ(DH_SUCCESS, sinkDev_->InitAVTransEngines(type, senderPtr)); + type = ChannelState::SPK_CONTROL_OPENED; + EXPECT_EQ(DH_SUCCESS, sinkDev_->InitAVTransEngines(type, receiverPtr)); } /**