From 598dd212d117404ff82275c18a72a523905812b3 Mon Sep 17 00:00:00 2001 From: yangwei_814916 Date: Wed, 13 Mar 2024 19:31:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=A3=80=E8=A7=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yangwei_814916 --- .../managersource/include/daudio_io_dev.h | 66 + .../managersource/include/daudio_source_dev.h | 182 ++ .../include/daudio_source_manager.h | 115 ++ .../include/daudio_source_mgr_callback.h | 33 + .../managersource/include/dmic_dev.h | 137 ++ .../managersource/include/dspeaker_dev.h | 121 ++ .../managersource/src/daudio_source_dev.cpp | 1565 +++++++++++++++++ .../src/daudio_source_manager.cpp | 611 +++++++ .../src/daudio_source_mgr_callback.cpp | 34 + .../audiocheck/managersource/src/dmic_dev.cpp | 528 ++++++ .../managersource/src/dspeaker_dev.cpp | 480 +++++ 11 files changed, 3872 insertions(+) create mode 100644 services/audiocheck/managersource/include/daudio_io_dev.h create mode 100644 services/audiocheck/managersource/include/daudio_source_dev.h create mode 100644 services/audiocheck/managersource/include/daudio_source_manager.h create mode 100644 services/audiocheck/managersource/include/daudio_source_mgr_callback.h create mode 100644 services/audiocheck/managersource/include/dmic_dev.h create mode 100644 services/audiocheck/managersource/include/dspeaker_dev.h create mode 100644 services/audiocheck/managersource/src/daudio_source_dev.cpp create mode 100644 services/audiocheck/managersource/src/daudio_source_manager.cpp create mode 100644 services/audiocheck/managersource/src/daudio_source_mgr_callback.cpp create mode 100644 services/audiocheck/managersource/src/dmic_dev.cpp create mode 100644 services/audiocheck/managersource/src/dspeaker_dev.cpp diff --git a/services/audiocheck/managersource/include/daudio_io_dev.h b/services/audiocheck/managersource/include/daudio_io_dev.h new file mode 100644 index 00000000..4953afd1 --- /dev/null +++ b/services/audiocheck/managersource/include/daudio_io_dev.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 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 OHOS_DAUDIO_IO_DEV_H +#define OHOS_DAUDIO_IO_DEV_H + +#include +#include +#include + +#include "audio_param.h" +#include "audio_status.h" +#include "av_receiver_engine_transport.h" +#include "ashmem.h" +#include "daudio_hdi_handler.h" +#include "iaudio_data_transport.h" +#include "iaudio_datatrans_callback.h" +#include "iaudio_event_callback.h" +#include "idaudio_hdi_callback.h" + +namespace OHOS { +namespace DistributedHardware { +class DAudioIoDev : public IDAudioHdiCallback { +public: + DAudioIoDev(const std::string &devId) + : devId_(devId) {}; + ~DAudioIoDev() override = default; + virtual int32_t InitReceiverEngine(IAVEngineProvider *providerPtr) = 0; + virtual int32_t InitSenderEngine(IAVEngineProvider *providerPtr) = 0; + + virtual int32_t EnableDevice(const int32_t dhId, const std::string &capability) = 0; + virtual int32_t DisableDevice(const int32_t dhId) = 0; + + virtual int32_t MmapStart() = 0; + virtual int32_t MmapStop() = 0; + + virtual int32_t SetUp() = 0; + virtual int32_t Start() = 0; + virtual int32_t Pause() = 0; + virtual int32_t Restart() = 0; + virtual int32_t Stop() = 0; + virtual int32_t Release() = 0; + virtual bool IsOpened() = 0; + virtual int32_t SendMessage(uint32_t type, std::string content, std::string dstDevId) = 0; + + virtual AudioParam GetAudioParam() const = 0; + virtual int32_t NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId) = 0; + +protected: + const std::string devId_; +}; +} // DistributedHardware +} // OHOS +#endif // OHOS_DAUDIO_IO_DEV_H \ No newline at end of file diff --git a/services/audiocheck/managersource/include/daudio_source_dev.h b/services/audiocheck/managersource/include/daudio_source_dev.h new file mode 100644 index 00000000..87e56b74 --- /dev/null +++ b/services/audiocheck/managersource/include/daudio_source_dev.h @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2022-2023 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 OHOS_DAUDIO_SOURCE_DEV_H +#define OHOS_DAUDIO_SOURCE_DEV_H + +#include +#include +#include +#include "cJSON.h" + +#include "event_handler.h" + +#include "audio_event.h" +#include "daudio_io_dev.h" +#include "daudio_source_dev_ctrl_mgr.h" +#include "daudio_source_mgr_callback.h" +#include "dmic_dev.h" +#include "dspeaker_dev.h" +#include "iaudio_event_callback.h" +#include "iaudio_data_transport.h" +#include "iaudio_datatrans_callback.h" +#include "idaudio_ipc_callback.h" +#include "idaudio_hdi_callback.h" + +namespace OHOS { +namespace DistributedHardware { +class DAudioSourceDev : public IAudioEventCallback, public std::enable_shared_from_this { +public: + DAudioSourceDev(const std::string &devId, const std::shared_ptr &callback); + ~DAudioSourceDev() override = default; + + int32_t AwakeAudioDev(); + void SleepAudioDev(); + + int32_t EnableDAudio(const std::string &dhId, const std::string &attrs); + int32_t DisableDAudio(const std::string &dhId); + int32_t RestoreThreadStatus(); + void SetThreadStatusFlag(); + bool GetThreadStatusFlag(); + void NotifyEvent(const AudioEvent &event) override; + +private: + int32_t EnableDSpeaker(const int32_t dhId, const std::string &attrs); + int32_t EnableDMic(const int32_t dhId, const std::string &attrs); + int32_t DisableDSpeaker(const int32_t dhId); + int32_t DisableDMic(const int32_t dhId); + int32_t DisableDAudioInner(const std::string &dhId); + + int32_t TaskEnableDAudio(const std::string &args); + int32_t TaskDisableDAudio(const std::string &args); + int32_t TaskOpenDSpeaker(const std::string &args); + int32_t OpenDSpeakerInner(std::shared_ptr &speaker, const int32_t dhId); + int32_t TaskCloseDSpeaker(const std::string &args); + int32_t TaskOpenDMic(const std::string &args); + int32_t TaskCloseDMic(const std::string &args); + int32_t TaskDMicClosed(const std::string &args); + int32_t TaskSetVolume(const std::string &args); + int32_t TaskChangeVolume(const std::string &args); + int32_t TaskChangeFocus(const std::string &args); + int32_t TaskChangeRenderState(const std::string &args); + int32_t TaskPlayStatusChange(const std::string &args); + int32_t TaskSpkMmapStart(const std::string &args); + int32_t TaskSpkMmapStop(const std::string &args); + int32_t TaskMicMmapStart(const std::string &args); + int32_t TaskMicMmapStop(const std::string &args); + + void OnDisableTaskResult(int32_t resultCode, const std::string &result, const std::string &funcName); + void OnEnableTaskResult(int32_t resultCode, const std::string &result, const std::string &funcName); + void OnTaskResult(int32_t resultCode, const std::string &result, const std::string &funcName); + + int32_t HandleOpenDSpeaker(const AudioEvent &event); + int32_t HandleCloseDSpeaker(const AudioEvent &event); + int32_t HandleDSpeakerOpened(const AudioEvent &event); + int32_t HandleDSpeakerClosed(const AudioEvent &event); + int32_t HandleOpenDMic(const AudioEvent &event); + int32_t HandleCloseDMic(const AudioEvent &event); + int32_t HandleDMicOpened(const AudioEvent &event); + int32_t HandleDMicClosed(const AudioEvent &event); + int32_t HandleCtrlTransClosed(const AudioEvent &event); + int32_t HandleNotifyRPC(const AudioEvent &event); + int32_t WaitForRPC(const AudioEventType type); + int32_t HandleVolumeSet(const AudioEvent &event); + int32_t HandleVolumeChange(const AudioEvent &event); + int32_t HandleFocusChange(const AudioEvent &event); + int32_t HandleRenderStateChange(const AudioEvent &event); + int32_t HandlePlayStatusChange(const AudioEvent &event); + int32_t HandleSpkMmapStart(const AudioEvent &event); + int32_t HandleSpkMmapStop(const AudioEvent &event); + int32_t HandleMicMmapStart(const AudioEvent &event); + int32_t HandleMicMmapStop(const AudioEvent &event); + + int32_t NotifySinkDev(const AudioEventType type, const cJSON *Param, const std::string dhId); + int32_t NotifyHDF(const AudioEventType type, const std::string result, const int32_t dhId); + AudioEventType getEventTypeFromArgs(const std::string &args); + void to_json(cJSON *j, const AudioParam ¶m); + int32_t SendAudioEventToRemote(const AudioEvent &event); + int32_t CloseSpkNew(const std::string &args); + int32_t CloseMicNew(const std::string &args); + std::shared_ptr FindIoDevImpl(std::string args); + int32_t ParseDhidFromEvent(std::string args); + int32_t ConvertString2Int(std::string val); + +private: + static constexpr uint8_t RPC_WAIT_SECONDS = 10; + static constexpr uint8_t TASK_QUEUE_CAPACITY = 20; + static constexpr uint8_t EVENT_NOTIFY_OPEN_SPK = 0x01; + static constexpr uint8_t EVENT_NOTIFY_CLOSE_SPK = 0x02; + static constexpr uint8_t EVENT_NOTIFY_OPEN_MIC = 0x04; + static constexpr uint8_t EVENT_NOTIFY_CLOSE_MIC = 0x08; + static constexpr uint8_t EVENT_NOTIFY_OPEN_CTRL = 0x10; + static constexpr uint8_t EVENT_NOTIFY_CLOSE_CTRL = 0x20; + static constexpr size_t WAIT_HANDLER_IDLE_TIME_US = 10000; + + std::string devId_; + std::shared_ptr mgrCallback_; + std::mutex ioDevMtx_; + std::map> deviceMap_; + std::shared_ptr speaker_; + std::shared_ptr mic_; + std::shared_ptr audioCtrlMgr_; + + std::mutex rpcWaitMutex_; + std::condition_variable rpcWaitCond_; + std::atomic isRpcOpen_ = false; + int32_t rpcResult_ = ERR_DH_AUDIO_FAILED; + uint8_t rpcNotify_ = 0; + std::atomic threadStatusFlag_ = false; + + class SourceEventHandler : public AppExecFwk::EventHandler { + public: + SourceEventHandler(const std::shared_ptr &runner, + const std::shared_ptr &dev); + ~SourceEventHandler() override; + void ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) override; + + private: + void EnableDAudioCallback(const AppExecFwk::InnerEvent::Pointer &event); + void DisableDAudioCallback(const AppExecFwk::InnerEvent::Pointer &event); + void OpenDSpeakerCallback(const AppExecFwk::InnerEvent::Pointer &event); + void CloseDSpeakerCallback(const AppExecFwk::InnerEvent::Pointer &event); + void OpenDMicCallback(const AppExecFwk::InnerEvent::Pointer &event); + void CloseDMicCallback(const AppExecFwk::InnerEvent::Pointer &event); + void DMicClosedCallback(const AppExecFwk::InnerEvent::Pointer &event); + void SetVolumeCallback(const AppExecFwk::InnerEvent::Pointer &event); + void ChangeVolumeCallback(const AppExecFwk::InnerEvent::Pointer &event); + void ChangeFocusCallback(const AppExecFwk::InnerEvent::Pointer &event); + void ChangeRenderStateCallback(const AppExecFwk::InnerEvent::Pointer &event); + void PlayStatusChangeCallback(const AppExecFwk::InnerEvent::Pointer &event); + void SpkMmapStartCallback(const AppExecFwk::InnerEvent::Pointer &event); + void SpkMmapStopCallback(const AppExecFwk::InnerEvent::Pointer &event); + void MicMmapStartCallback(const AppExecFwk::InnerEvent::Pointer &event); + void MicMmapStopCallback(const AppExecFwk::InnerEvent::Pointer &event); + void SetThreadStatusFlagTrue(const AppExecFwk::InnerEvent::Pointer &event); + int32_t GetEventParam(const AppExecFwk::InnerEvent::Pointer &event, std::string &eventParam); + + private: + using SourceEventFunc = void (SourceEventHandler::*)(const AppExecFwk::InnerEvent::Pointer &event); + std::map mapEventFuncs_; + std::weak_ptr sourceDev_; + }; + + using DAudioSourceDevFunc = int32_t (DAudioSourceDev::*)(const AudioEvent &audioEvent); + std::map memberFuncMap_; + std::map eventNotifyMap_; + std::shared_ptr handler_; +}; +} // DistributedHardware +} // OHOS +#endif // OHOS_DAUDIO_SOURCE_DEV_H \ No newline at end of file diff --git a/services/audiocheck/managersource/include/daudio_source_manager.h b/services/audiocheck/managersource/include/daudio_source_manager.h new file mode 100644 index 00000000..e11e8ae5 --- /dev/null +++ b/services/audiocheck/managersource/include/daudio_source_manager.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2022-2023 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 OHOS_DAUDIO_SOURCE_MANAGER_H +#define OHOS_DAUDIO_SOURCE_MANAGER_H + +#include +#include +#include + +#include "event_handler.h" + +#include "daudio_hdi_handler.h" +#include "daudio_source_dev.h" +#include "daudio_source_mgr_callback.h" +#include "idaudio_sink.h" +#include "single_instance.h" + +namespace OHOS { +namespace DistributedHardware { +class DAudioSourceManager { + DECLARE_SINGLE_INSTANCE_BASE(DAudioSourceManager); + +public: + int32_t Init(const sptr &callback); + int32_t UnInit(); + int32_t EnableDAudio(const std::string &devId, const std::string &dhId, const std::string &version, + const std::string &attrs, const std::string &reqId); + int32_t DisableDAudio(const std::string &devId, const std::string &dhId, const std::string &reqId); + int32_t HandleDAudioNotify(const std::string &devId, const std::string &dhId, const int32_t eventType, + const std::string &eventContent); + int32_t DAudioNotify(const std::string &devId, const std::string &dhId, const int32_t eventType, + const std::string &eventContent); + int32_t OnEnableDAudio(const std::string &devId, const std::string &dhId, const int32_t result); + int32_t OnDisableDAudio(const std::string &devId, const std::string &dhId, const int32_t result); + int32_t LoadAVSenderEngineProvider(); + int32_t UnloadAVSenderEngineProvider(); + int32_t LoadAVReceiverEngineProvider(); + int32_t UnloadAVReceiverEngineProvider(); + IAVEngineProvider *getSenderProvider(); + IAVEngineProvider *getReceiverProvider(); + +private: + DAudioSourceManager(); + ~DAudioSourceManager(); + int32_t CreateAudioDevice(const std::string &devId); + void DeleteAudioDevice(const std::string &devId, const std::string &dhId); + std::string GetRequestId(const std::string &devId, const std::string &dhId); + void ClearAudioDev(const std::string &devId); + void ListenAudioDev(); + void RestoreThreadStatus(); + int32_t DoEnableDAudio(const std::string &args); + int32_t DoDisableDAudio(const std::string &args); + + typedef struct { + std::string devId; + std::shared_ptr dev; + std::map ports; + } AudioDevice; + +private: + static constexpr const char* DEVCLEAR_THREAD = "sourceClearTh"; + static constexpr const char* LISTEN_THREAD = "sourceListenTh"; + static constexpr int32_t WATCHDOG_INTERVAL_TIME = 20000; + static constexpr int32_t WATCHDOG_DELAY_TIME = 5000; + static constexpr size_t SLEEP_TIME = 1000000; + static constexpr size_t WAIT_HANDLER_IDLE_TIME_US = 10000; + + std::string localDevId_; + std::mutex devMapMtx_; + std::map audioDevMap_; + std::mutex remoteSvrMutex_; + std::map> sinkServiceMap_; + sptr ipcCallback_ = nullptr; + std::shared_ptr daudioMgrCallback_ = nullptr; + std::thread devClearThread_; + std::thread listenThread_; + IAVEngineProvider *sendProviderPtr_ = nullptr; + IAVEngineProvider *rcvProviderPtr_ = nullptr; + void *pSHandler_ = nullptr; + void *pRHandler_ = nullptr; + std::atomic isHicollieRunning_ = false; + + 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_; + }; + std::shared_ptr handler_; +}; +} // DistributedHardware +} // OHOS +#endif // OHOS_DAUDIO_SINK_MANAGER_H diff --git a/services/audiocheck/managersource/include/daudio_source_mgr_callback.h b/services/audiocheck/managersource/include/daudio_source_mgr_callback.h new file mode 100644 index 00000000..3f048333 --- /dev/null +++ b/services/audiocheck/managersource/include/daudio_source_mgr_callback.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022 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 OHOS_DAUDIO_SOURCE_MGR_CALLBACK_H +#define OHOS_DAUDIO_SOURCE_MGR_CALLBACK_H + +#include + +namespace OHOS { +namespace DistributedHardware { +class DAudioSourceMgrCallback { +public: + DAudioSourceMgrCallback() = default; + ~DAudioSourceMgrCallback() = default; + + int32_t OnEnableAudioResult(const std::string &devId, const std::string &dhId, const int32_t result); + int32_t OnDisableAudioResult(const std::string &devId, const std::string &dhId, const int32_t result); +}; +} // DistributedHardware +} // OHOS +#endif // OHOS_DAUDIO_SOURCE_MGR_CALLBACK_H \ No newline at end of file diff --git a/services/audiocheck/managersource/include/dmic_dev.h b/services/audiocheck/managersource/include/dmic_dev.h new file mode 100644 index 00000000..41786ab5 --- /dev/null +++ b/services/audiocheck/managersource/include/dmic_dev.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2022-2023 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 OHOS_DMIC_DEV_H +#define OHOS_DMIC_DEV_H + +#include +#include +#include +#include "cJSON.h" + +#include "audio_param.h" +#include "audio_status.h" +#include "av_receiver_engine_transport.h" +#include "ashmem.h" +#include "daudio_constants.h" +#include "daudio_hdi_handler.h" +#include "daudio_io_dev.h" +#include "iaudio_data_transport.h" +#include "iaudio_datatrans_callback.h" +#include "iaudio_event_callback.h" +#include "idaudio_hdi_callback.h" + +namespace OHOS { +namespace DistributedHardware { +class DMicDev : public DAudioIoDev, + public IAudioDataTransCallback, + public AVReceiverTransportCallback, + public std::enable_shared_from_this { +public: + DMicDev(const std::string &devId, std::shared_ptr callback) + : DAudioIoDev(devId), audioEventCallback_(callback) {}; + ~DMicDev() override = default; + + void OnEngineTransEvent(const AVTransEvent &event) override; + void OnEngineTransMessage(const std::shared_ptr &message) override; + void OnEngineTransDataAvailable(const std::shared_ptr &audioData) override; + + int32_t InitReceiverEngine(IAVEngineProvider *providerPtr) override; + int32_t InitSenderEngine(IAVEngineProvider *providerPtr) override; + + int32_t EnableDevice(const int32_t dhId, const std::string &capability) override; + int32_t DisableDevice(const int32_t dhId) override; + int32_t OpenDevice(const std::string &devId, const int32_t dhId) override; + int32_t CloseDevice(const std::string &devId, const int32_t dhId) override; + int32_t SetParameters(const std::string &devId, const int32_t dhId, const AudioParamHDF ¶m) override; + int32_t WriteStreamData(const std::string &devId, const int32_t dhId, std::shared_ptr &data) override; + int32_t ReadStreamData(const std::string &devId, const int32_t dhId, std::shared_ptr &data) override; + int32_t NotifyEvent(const std::string &devId, const int32_t dhId, const AudioEvent &event) override; + int32_t ReadMmapPosition(const std::string &devId, const int32_t dhId, + uint64_t &frames, CurrentTimeHDF &time) override; + int32_t RefreshAshmemInfo(const std::string &devId, const int32_t dhId, + int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans) override; + + int32_t MmapStart() override; + int32_t MmapStop() override; + + int32_t SetUp() override; + int32_t Start() override; + int32_t Pause() override; + int32_t Restart() override; + int32_t Stop() override; + int32_t Release() override; + bool IsOpened() override; + int32_t SendMessage(uint32_t type, std::string content, std::string dstDevId) override; + + AudioParam GetAudioParam() const override; + int32_t NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId) override; + + int32_t OnStateChange(const AudioEventType type) override; + int32_t OnDecodeTransDataDone(const std::shared_ptr &audioData) override; + +private: + void EnqueueThread(); + void FillJitterQueue(); + +private: + static constexpr uint8_t CHANNEL_WAIT_SECONDS = 5; + static constexpr size_t DATA_QUEUE_MAX_SIZE = 10; + static constexpr size_t DATA_QUEUE_HALF_SIZE = DATA_QUEUE_MAX_SIZE >> 1U; + static constexpr size_t LOW_LATENCY_DATA_QUEUE_MAX_SIZE = 30; + static constexpr size_t LOW_LATENCY_DATA_QUEUE_HALF_SIZE = 10; + static constexpr uint32_t MMAP_WAIT_FRAME_US = 5000; + static constexpr const char* ENQUEUE_THREAD = "micEnqueueTh"; + const std::string MIC_DEV_FILENAME = DUMP_FILE_PATH + "/source_mic_read_from_trans.pcm"; + const std::string MIC_LOWLATENCY_FILENAME = DUMP_FILE_PATH + "/source_mic_write_to_ashmem.pcm"; + + std::weak_ptr audioEventCallback_; + std::mutex dataQueueMtx_; + std::mutex channelWaitMutex_; + std::condition_variable channelWaitCond_; + int32_t curPort_ = 0; + std::atomic isTransReady_ = false; + std::atomic isOpened_ = false; + std::atomic dumpFlag_ = false; + std::shared_ptr micTrans_ = nullptr; + std::queue> dataQueue_; + AudioStatus curStatus_ = AudioStatus::STATUS_IDLE; + // Mic capture parameters + AudioParamHDF paramHDF_; + AudioParam param_; + + uint32_t timeInterval_ = 5; + uint32_t insertFrameCnt_ = 0; + std::atomic isExistedEmpty_ = false; + size_t dataQueSize_ = 0; + sptr ashmem_ = nullptr; + std::atomic isEnqueueRunning_ = false; + int32_t ashmemLength_ = -1; + int32_t lengthPerTrans_ = -1; + int32_t writeIndex_ = -1; + int64_t frameIndex_ = 0; + int64_t startTime_ = 0; + uint64_t writeNum_ = 0; + int64_t writeTvSec_ = 0; + int64_t writeTvNSec_ = 0; + int64_t lastReadStartTime_ = 0; + std::thread enqueueDataThread_; + std::mutex writeAshmemMutex_; + std::condition_variable dataQueueCond_; + int32_t dhId_ = -1; +}; +} // DistributedHardware +} // OHOS +#endif // OHOS_DAUDIO_DMIC_DEV_H diff --git a/services/audiocheck/managersource/include/dspeaker_dev.h b/services/audiocheck/managersource/include/dspeaker_dev.h new file mode 100644 index 00000000..c6c836a6 --- /dev/null +++ b/services/audiocheck/managersource/include/dspeaker_dev.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2022-2023 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 OHOS_DSPEAKER_DEV_H +#define OHOS_DSPEAKER_DEV_H + +#include +#include +#include +#include "cJSON.h" + +#include "audio_param.h" +#include "ashmem.h" +#include "av_sender_engine_transport.h" +#include "daudio_constants.h" +#include "daudio_hdi_handler.h" +#include "daudio_io_dev.h" +#include "iaudio_event_callback.h" +#include "iaudio_data_transport.h" +#include "iaudio_datatrans_callback.h" +#include "idaudio_hdi_callback.h" + +namespace OHOS { +namespace DistributedHardware { +class DSpeakerDev : public DAudioIoDev, + public IAudioDataTransCallback, + public AVSenderTransportCallback, + public std::enable_shared_from_this { +public: + DSpeakerDev(const std::string &devId, std::shared_ptr callback) + : DAudioIoDev(devId), audioEventCallback_(callback) {}; + ~DSpeakerDev() override = default; + + void OnEngineTransEvent(const AVTransEvent &event) override; + void OnEngineTransMessage(const std::shared_ptr &message) override; + + int32_t InitReceiverEngine(IAVEngineProvider *providerPtr) override; + int32_t InitSenderEngine(IAVEngineProvider *providerPtr) override; + + int32_t EnableDevice(const int32_t dhId, const std::string &capability) override; + int32_t DisableDevice(const int32_t dhId) override; + int32_t OpenDevice(const std::string &devId, const int32_t dhId) override; + int32_t CloseDevice(const std::string &devId, const int32_t dhId) override; + int32_t SetParameters(const std::string &devId, const int32_t dhId, const AudioParamHDF ¶m) override; + int32_t WriteStreamData(const std::string &devId, const int32_t dhId, std::shared_ptr &data) override; + int32_t ReadStreamData(const std::string &devId, const int32_t dhId, std::shared_ptr &data) override; + int32_t NotifyEvent(const std::string &devId, const int32_t dhId, const AudioEvent &event) override; + int32_t ReadMmapPosition(const std::string &devId, const int32_t dhId, + uint64_t &frames, CurrentTimeHDF &time) override; + int32_t RefreshAshmemInfo(const std::string &devId, const int32_t dhId, + int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans) override; + + int32_t MmapStart() override; + int32_t MmapStop() override; + + int32_t OnStateChange(const AudioEventType type) override; + int32_t OnDecodeTransDataDone(const std::shared_ptr &audioData) override; + + int32_t SetUp() override; + int32_t Start() override; + int32_t Stop() override; + int32_t Release() override; + bool IsOpened() override; + int32_t Pause() override; + int32_t Restart() override; + int32_t SendMessage(uint32_t type, std::string content, std::string dstDevId) override; + + AudioParam GetAudioParam() const override; + int32_t NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId) override; + +private: + void EnqueueThread(); + +private: + static constexpr const char* ENQUEUE_THREAD = "spkEnqueueTh"; + const std::string SPK_DEV_FILENAME = DUMP_FILE_PATH + "/source_spk_write_to_trans.pcm"; + const std::string SPK_LOWLATENCY_FILENAME = DUMP_FILE_PATH + "/source_spk_read_from_ashmem.pcm"; + + std::weak_ptr audioEventCallback_; + std::mutex channelWaitMutex_; + std::condition_variable channelWaitCond_; + std::atomic isTransReady_ = false; + std::atomic isOpened_ = false; + std::atomic dumpFlag_ = false; + int32_t curPort_ = 0; + std::shared_ptr speakerTrans_ = nullptr; + + // Speaker render parameters + AudioParamHDF paramHDF_; + AudioParam param_; + + uint32_t timeInterval_ = 5; + sptr ashmem_ = nullptr; + std::atomic isEnqueueRunning_ = false; + int32_t ashmemLength_ = -1; + int32_t lengthPerTrans_ = -1; + int32_t readIndex_ = -1; + int64_t frameIndex_ = 0; + int64_t startTime_ = 0; + uint64_t readNum_ = 0; + int64_t readTvSec_ = 0; + int64_t readTvNSec_ = 0; + std::thread enqueueDataThread_; + int64_t lastwriteStartTime_ = 0; + int32_t dhId_ = -1; +}; +} // DistributedHardware +} // OHOS +#endif // OHOS_DAUDIO_DSPEAKER_DEV_H \ No newline at end of file diff --git a/services/audiocheck/managersource/src/daudio_source_dev.cpp b/services/audiocheck/managersource/src/daudio_source_dev.cpp new file mode 100644 index 00000000..ec9b47cf --- /dev/null +++ b/services/audiocheck/managersource/src/daudio_source_dev.cpp @@ -0,0 +1,1565 @@ +/* + * Copyright (c) 2022-2023 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 "daudio_source_dev.h" + +#include + +#include "cJSON.h" + +#include "daudio_constants.h" +#include "daudio_errorcode.h" +#include "daudio_hitrace.h" +#include "daudio_log.h" +#include "daudio_source_manager.h" +#include "daudio_util.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "DAudioSourceDev" + +namespace OHOS { +namespace DistributedHardware { +namespace { +constexpr uint32_t EVENT_OPEN_SPEAKER = 11; +constexpr uint32_t EVENT_CLOSE_SPEAKER = 12; +constexpr uint32_t EVENT_OPEN_MIC = 21; +constexpr uint32_t EVENT_CLOSE_MIC = 22; +constexpr uint32_t EVENT_DMIC_CLOSED = 24; +constexpr uint32_t EVENT_VOLUME_SET = 31; +constexpr uint32_t EVENT_VOLUME_CHANGE = 33; +constexpr uint32_t EVENT_AUDIO_FOCUS_CHANGE = 41; +constexpr uint32_t EVENT_AUDIO_RENDER_STATE_CHANGE = 42; +constexpr uint32_t EVENT_CHANGE_PLAY_STATUS = 71; +constexpr uint32_t EVENT_MMAP_SPK_START = 81; +constexpr uint32_t EVENT_MMAP_SPK_STOP = 82; +constexpr uint32_t EVENT_MMAP_MIC_START = 83; +constexpr uint32_t EVENT_MMAP_MIC_STOP = 84; +constexpr uint32_t EVENT_DAUDIO_ENABLE = 88; +constexpr uint32_t EVENT_DAUDIO_DISABLE = 89; +constexpr uint32_t EVENT_SET_THREAD_STATUS = 90; +} + +DAudioSourceDev::DAudioSourceDev(const std::string &devId, const std::shared_ptr &callback) + : devId_(devId), mgrCallback_(callback) +{ + memberFuncMap_[OPEN_SPEAKER] = &DAudioSourceDev::HandleOpenDSpeaker; + memberFuncMap_[CLOSE_SPEAKER] = &DAudioSourceDev::HandleCloseDSpeaker; + memberFuncMap_[SPEAKER_OPENED] = &DAudioSourceDev::HandleDSpeakerOpened; + memberFuncMap_[SPEAKER_CLOSED] = &DAudioSourceDev::HandleDSpeakerClosed; + memberFuncMap_[NOTIFY_OPEN_SPEAKER_RESULT] = &DAudioSourceDev::HandleNotifyRPC; + memberFuncMap_[NOTIFY_CLOSE_SPEAKER_RESULT] = &DAudioSourceDev::HandleNotifyRPC; + memberFuncMap_[OPEN_MIC] = &DAudioSourceDev::HandleOpenDMic; + memberFuncMap_[CLOSE_MIC] = &DAudioSourceDev::HandleCloseDMic; + memberFuncMap_[MIC_OPENED] = &DAudioSourceDev::HandleDMicOpened; + memberFuncMap_[MIC_CLOSED] = &DAudioSourceDev::HandleDMicClosed; + memberFuncMap_[NOTIFY_OPEN_MIC_RESULT] = &DAudioSourceDev::HandleNotifyRPC; + memberFuncMap_[NOTIFY_CLOSE_MIC_RESULT] = &DAudioSourceDev::HandleNotifyRPC; + memberFuncMap_[NOTIFY_OPEN_CTRL_RESULT] = &DAudioSourceDev::HandleNotifyRPC; + memberFuncMap_[NOTIFY_CLOSE_CTRL_RESULT] = &DAudioSourceDev::HandleNotifyRPC; + memberFuncMap_[CTRL_CLOSED] = &DAudioSourceDev::HandleCtrlTransClosed; + memberFuncMap_[VOLUME_SET] = &DAudioSourceDev::HandleVolumeSet; + memberFuncMap_[VOLUME_MUTE_SET] = &DAudioSourceDev::HandleVolumeSet; + memberFuncMap_[VOLUME_CHANGE] = &DAudioSourceDev::HandleVolumeChange; + memberFuncMap_[AUDIO_FOCUS_CHANGE] = &DAudioSourceDev::HandleFocusChange; + memberFuncMap_[AUDIO_RENDER_STATE_CHANGE] = &DAudioSourceDev::HandleRenderStateChange; + memberFuncMap_[CHANGE_PLAY_STATUS] = &DAudioSourceDev::HandlePlayStatusChange; + memberFuncMap_[MMAP_SPK_START] = &DAudioSourceDev::HandleSpkMmapStart; + memberFuncMap_[MMAP_SPK_STOP] = &DAudioSourceDev::HandleSpkMmapStop; + memberFuncMap_[MMAP_MIC_START] = &DAudioSourceDev::HandleMicMmapStart; + memberFuncMap_[MMAP_MIC_STOP] = &DAudioSourceDev::HandleMicMmapStop; + + eventNotifyMap_[NOTIFY_OPEN_SPEAKER_RESULT] = EVENT_NOTIFY_OPEN_SPK; + eventNotifyMap_[NOTIFY_CLOSE_SPEAKER_RESULT] = EVENT_NOTIFY_CLOSE_SPK; + eventNotifyMap_[NOTIFY_OPEN_MIC_RESULT] = EVENT_NOTIFY_OPEN_MIC; + eventNotifyMap_[NOTIFY_CLOSE_MIC_RESULT] = EVENT_NOTIFY_CLOSE_MIC; + eventNotifyMap_[NOTIFY_OPEN_CTRL_RESULT] = EVENT_NOTIFY_OPEN_CTRL; + eventNotifyMap_[NOTIFY_CLOSE_CTRL_RESULT] = EVENT_NOTIFY_CLOSE_CTRL; +} + +int32_t DAudioSourceDev::AwakeAudioDev() +{ + auto runner = AppExecFwk::EventRunner::Create(true); + CHECK_NULL_RETURN(runner, ERR_DH_AUDIO_NULLPTR); + handler_ = std::make_shared(runner, shared_from_this()); + return DH_SUCCESS; +} + +void DAudioSourceDev::SleepAudioDev() +{ + DHLOGD("Sleep audio dev."); + CHECK_NULL_VOID(handler_); + while (!handler_->IsIdle()) { + DHLOGD("handler is running, wait for idle."); + usleep(WAIT_HANDLER_IDLE_TIME_US); + } + DHLOGI("Sleep audio dev over."); +} + +int32_t DAudioSourceDev::EnableDAudio(const std::string &dhId, const std::string &attrs) +{ + DHLOGI("Enable audio device, dhId: %{public}s.", dhId.c_str()); + isRpcOpen_.store(true); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + + cJSON *jParam = cJSON_CreateObject(); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + cJSON_AddStringToObject(jParam, KEY_DEV_ID, devId_.c_str()); + cJSON_AddStringToObject(jParam, KEY_DH_ID, dhId.c_str()); + cJSON_AddStringToObject(jParam, KEY_ATTRS, attrs.c_str()); + char *jsonString = cJSON_PrintUnformatted(jParam); + if (jsonString == nullptr) { + DHLOGE("Failed to create JSON data"); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NULLPTR; + } + auto eventParam = std::make_shared(jsonString); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_DAUDIO_ENABLE, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + cJSON_Delete(jParam); + cJSON_free(jsonString); + return ERR_DH_AUDIO_FAILED; + } + DHLOGI("Enable audio task generate successfully."); + cJSON_Delete(jParam); + cJSON_free(jsonString); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::DisableDAudioInner(const std::string &dhId) +{ + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + cJSON *jParam = cJSON_CreateObject(); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + cJSON_AddStringToObject(jParam, KEY_DEV_ID, devId_.c_str()); + cJSON_AddStringToObject(jParam, KEY_DH_ID, dhId.c_str()); + char *jsonString = cJSON_PrintUnformatted(jParam); + if (jsonString == nullptr) { + DHLOGE("Failed to create JSON data"); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NULLPTR; + } + auto eventParam = std::make_shared(jsonString); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_DAUDIO_DISABLE, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + cJSON_Delete(jParam); + cJSON_free(jsonString); + return ERR_DH_AUDIO_FAILED; + } + cJSON_Delete(jParam); + cJSON_free(jsonString); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::DisableDAudio(const std::string &dhId) +{ + DHLOGI("Disable audio device, dhId: %{public}s.", dhId.c_str()); + isRpcOpen_.store(false); + + cJSON *jParamClose = cJSON_CreateObject(); + CHECK_NULL_RETURN(jParamClose, ERR_DH_AUDIO_NULLPTR); + cJSON_AddStringToObject(jParamClose, KEY_DH_ID, dhId.c_str()); + char *data = cJSON_PrintUnformatted(jParamClose); + if (data == nullptr) { + DHLOGE("Failed to create JSON data."); + cJSON_Delete(jParamClose); + return ERR_DH_AUDIO_NULLPTR; + } + AudioEvent event(AudioEventType::EVENT_UNKNOWN, std::string(data)); + int32_t dhIdNum = ConvertString2Int(dhId); + CHECK_AND_FREECHAR_RETURN_RET_LOG(dhIdNum == -1, ERR_DH_AUDIO_NOT_SUPPORT, data, "%{public}s", "Parse dhId error."); + switch (GetDevTypeByDHId(dhIdNum)) { + case AUDIO_DEVICE_TYPE_SPEAKER: + event.type = CLOSE_SPEAKER; + HandleCloseDSpeaker(event); + break; + case AUDIO_DEVICE_TYPE_MIC: + event.type = CLOSE_MIC; + HandleCloseDMic(event); + break; + default: + cJSON_Delete(jParamClose); + cJSON_free(data); + DHLOGE("Unknown audio device. dhId: %{public}d.", dhIdNum); + return ERR_DH_AUDIO_NOT_SUPPORT; + } + cJSON_Delete(jParamClose); + cJSON_free(data); + int32_t ret = DisableDAudioInner(dhId); + if (ret != DH_SUCCESS) { + DHLOGE("Failed to disable audio device, result is: %{public}d.", ret); + return ret; + } + DHLOGI("Disable audio task generate successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::RestoreThreadStatus() +{ + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + cJSON *jParam = cJSON_CreateObject(); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + char *jsonString = cJSON_PrintUnformatted(jParam); + if (jsonString == nullptr) { + DHLOGE("Failed to create JSON data"); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NULLPTR; + } + auto eventParam = std::make_shared(jsonString); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_SET_THREAD_STATUS, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + cJSON_Delete(jParam); + cJSON_free(jsonString); + return ERR_DH_AUDIO_FAILED; + } + cJSON_Delete(jParam); + cJSON_free(jsonString); + return DH_SUCCESS; +} + +bool DAudioSourceDev::GetThreadStatusFlag() +{ + return threadStatusFlag_; +} + +void DAudioSourceDev::SetThreadStatusFlag() +{ + threadStatusFlag_ = false; +} + +void DAudioSourceDev::NotifyEvent(const AudioEvent &event) +{ + DHLOGD("Notify event, eventType: %{public}d.", event.type); + std::map::iterator iter = memberFuncMap_.find(event.type); + if (iter == memberFuncMap_.end()) { + DHLOGE("Invalid eventType: %{public}d.", event.type); + return; + } + DAudioSourceDevFunc &func = iter->second; + (this->*func)(event); +} + +int32_t DAudioSourceDev::HandleOpenDSpeaker(const AudioEvent &event) +{ + DHLOGI("Open speaker device."); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_OPEN_SPEAKER, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Opening DSpeaker event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleCloseDSpeaker(const AudioEvent &event) +{ + DHLOGI("Close speaker device."); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_CLOSE_SPEAKER, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Closing DSpeaker event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleDSpeakerOpened(const AudioEvent &event) +{ + (void)event; + DHLOGI("Speaker device opened."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleDSpeakerClosed(const AudioEvent &event) +{ + DHLOGI("Speaker device closed, event.content = %{public}s.", event.content.c_str()); + int32_t dhId = ParseDhidFromEvent(event.content); + if (dhId < 0) { + DHLOGE("Failed to parse dhardware id."); + return ERR_DH_AUDIO_FAILED; + } + auto speaker = FindIoDevImpl(event.content); + CHECK_NULL_RETURN(speaker, ERR_DH_AUDIO_NULLPTR); + return speaker->NotifyHdfAudioEvent(event, dhId); +} + +std::shared_ptr DAudioSourceDev::FindIoDevImpl(std::string args) +{ + int32_t dhId = ParseDhidFromEvent(args); + if (dhId < 0) { + DHLOGE("Failed to parse dhardware id."); + return nullptr; + } + std::lock_guard devLck(ioDevMtx_); + if (deviceMap_.find(dhId) == deviceMap_.end()) { + DHLOGE("Not find IO device instance."); + return nullptr; + } + return deviceMap_[dhId]; +} + +int32_t DAudioSourceDev::HandleOpenDMic(const AudioEvent &event) +{ + DHLOGI("Open mic device."); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_OPEN_MIC, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Opening DMic event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleCloseDMic(const AudioEvent &event) +{ + DHLOGI("Close mic device."); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_CLOSE_MIC, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Closing DMic event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleDMicOpened(const AudioEvent &event) +{ + (void)event; + DHLOGI("Mic device opened."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleDMicClosed(const AudioEvent &event) +{ + DHLOGI("Dmic device closed, event.content = %{public}s.", event.content.c_str()); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_DMIC_CLOSED, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Dmic closed event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleCtrlTransClosed(const AudioEvent &event) +{ + DHLOGI("Control trans closed."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleNotifyRPC(const AudioEvent &event) +{ + std::lock_guard dataLock(rpcWaitMutex_); + if (event.content.length() > DAUDIO_MAX_JSON_LEN || event.content.empty()) { + return ERR_DH_AUDIO_SA_PARAM_INVALID; + } + cJSON *jParam = cJSON_Parse(event.content.c_str()); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + if (!CJsonParamCheck(jParam, { KEY_RESULT })) { + DHLOGE("Not found the keys of result."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_FAILED; + } + + rpcResult_ = cJSON_GetObjectItem(jParam, KEY_RESULT)->valueint; + DHLOGD("Notify RPC event: %{public}d, result: %{public}d.", event.type, rpcResult_); + std::map::iterator iter = eventNotifyMap_.find(event.type); + if (iter == eventNotifyMap_.end()) { + DHLOGE("Invalid eventType."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NOT_FOUND_KEY; + } + rpcNotify_ = iter->second; + rpcWaitCond_.notify_all(); + cJSON_Delete(jParam); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleVolumeSet(const AudioEvent &event) +{ + DHLOGD("Start handle volume set."); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_VOLUME_SET, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Volume setting event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleVolumeChange(const AudioEvent &event) +{ + DHLOGD("Start handle volume change."); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_VOLUME_CHANGE, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Volume change event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleFocusChange(const AudioEvent &event) +{ + DHLOGD("Start handle focus change."); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_AUDIO_FOCUS_CHANGE, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Focus change event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleRenderStateChange(const AudioEvent &event) +{ + DHLOGD("Start handle render state change."); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_AUDIO_RENDER_STATE_CHANGE, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Render state change event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandlePlayStatusChange(const AudioEvent &event) +{ + DHLOGD("Play status change, content: %{public}s.", event.content.c_str()); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_CHANGE_PLAY_STATUS, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Play state change event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleSpkMmapStart(const AudioEvent &event) +{ + DHLOGI("Spk mmap start, content: %{public}s.", event.content.c_str()); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_MMAP_SPK_START, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Speaker Mmap Start event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleSpkMmapStop(const AudioEvent &event) +{ + DHLOGI("Spk mmap stop, content: %{public}s.", event.content.c_str()); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_MMAP_SPK_STOP, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Speaker Mmap Stop event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleMicMmapStart(const AudioEvent &event) +{ + DHLOGI("Mic mmap start, content: %{public}s.", event.content.c_str()); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_MMAP_MIC_START, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Mic Mmap Start event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::HandleMicMmapStop(const AudioEvent &event) +{ + DHLOGI("Mic mmap stop, content: %{public}s.", event.content.c_str()); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + auto eventParam = std::make_shared(event); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_MMAP_MIC_STOP, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + return ERR_DH_AUDIO_FAILED; + } + DHLOGD("Mic Mmap Stop event is sent successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::WaitForRPC(const AudioEventType type) +{ + std::unique_lock lck(rpcWaitMutex_); + DHLOGI("Wait sink device notify type: %{public}d.", type); + auto status = rpcWaitCond_.wait_for(lck, std::chrono::seconds(RPC_WAIT_SECONDS), [this, type]() { + switch (type) { + case AudioEventType::NOTIFY_OPEN_SPEAKER_RESULT: + return rpcNotify_ == EVENT_NOTIFY_OPEN_SPK; + case AudioEventType::NOTIFY_CLOSE_SPEAKER_RESULT: + return rpcNotify_ == EVENT_NOTIFY_CLOSE_SPK; + case AudioEventType::NOTIFY_OPEN_MIC_RESULT: + return rpcNotify_ == EVENT_NOTIFY_OPEN_MIC; + case AudioEventType::NOTIFY_CLOSE_MIC_RESULT: + return rpcNotify_ == EVENT_NOTIFY_CLOSE_MIC; + case AudioEventType::NOTIFY_OPEN_CTRL_RESULT: + return rpcNotify_ == EVENT_NOTIFY_OPEN_CTRL; + case AudioEventType::NOTIFY_CLOSE_CTRL_RESULT: + return rpcNotify_ == EVENT_NOTIFY_CLOSE_CTRL; + default: + return false; + } + }); + if (!status) { + DHLOGE("RPC notify wait timeout(%{public}ds).", RPC_WAIT_SECONDS); + return ERR_DH_AUDIO_SA_WAIT_TIMEOUT; + } + if (rpcResult_ != DH_SUCCESS) { + DHLOGE("RPC notify Result Failed."); + return rpcResult_; + } + rpcNotify_ = 0; + rpcResult_ = ERR_DH_AUDIO_FAILED; + DHLOGD("Receive sink device notify type: %{public}d.", type); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::TaskEnableDAudio(const std::string &args) +{ + DHLOGI("Enable audio device."); + if (args.length() > DAUDIO_MAX_JSON_LEN || args.empty()) { + return ERR_DH_AUDIO_SA_PARAM_INVALID; + } + cJSON *jParam = cJSON_Parse(args.c_str()); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + if (!CJsonParamCheck(jParam, { KEY_DH_ID, KEY_ATTRS })) { + DHLOGE("The keys or values is invalid."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_SA_PARAM_INVALID; + } + int32_t dhId = ParseDhidFromEvent(args); + if (dhId == -1) { + DHLOGE("Parse dhId error."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NOT_SUPPORT; + } + char *attrs = cJSON_PrintUnformatted(cJSON_GetObjectItem(jParam, KEY_ATTRS)); + if (attrs == nullptr) { + DHLOGE("Failed to create JSON data"); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NULLPTR; + } + std::string attrsStr(attrs); + int32_t result = 0; + switch (GetDevTypeByDHId(dhId)) { + case AUDIO_DEVICE_TYPE_SPEAKER: + result = EnableDSpeaker(dhId, attrsStr); + break; + case AUDIO_DEVICE_TYPE_MIC: + result = EnableDMic(dhId, attrsStr); + break; + default: + DHLOGE("Unknown audio device. dhId: %{public}d.", dhId); + result = ERR_DH_AUDIO_NOT_SUPPORT; + } + cJSON_Delete(jParam); + cJSON_free(attrs); + return result; +} + +int32_t DAudioSourceDev::EnableDSpeaker(const int32_t dhId, const std::string &attrs) +{ + std::lock_guard devLck(ioDevMtx_); + if (deviceMap_.find(dhId) != deviceMap_.end()) { + DHLOGI("The speaker device is already enabled."); + return DH_SUCCESS; + } + auto speaker = std::make_shared(devId_, shared_from_this()); + if (speaker->EnableDevice(dhId, attrs) != DH_SUCCESS) { + DHLOGI("Failed to enable speaker device."); + return ERR_DH_AUDIO_FAILED; + } + deviceMap_[dhId] = speaker; + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::EnableDMic(const int32_t dhId, const std::string &attrs) +{ + std::lock_guard devLck(ioDevMtx_); + if (deviceMap_.find(dhId) != deviceMap_.end()) { + DHLOGI("The mic device is already enabled."); + return DH_SUCCESS; + } + auto mic = std::make_shared(devId_, shared_from_this()); + if (mic->EnableDevice(dhId, attrs) != DH_SUCCESS) { + DHLOGI("Failed to enable mic device."); + return ERR_DH_AUDIO_FAILED; + } + deviceMap_[dhId] = mic; + return DH_SUCCESS; +} + +void DAudioSourceDev::OnEnableTaskResult(int32_t resultCode, const std::string &result, const std::string &funcName) +{ + (void)funcName; + DHLOGI("On enable task result."); + CHECK_NULL_VOID(mgrCallback_); + if (result.length() > DAUDIO_MAX_JSON_LEN || result.empty()) { + return; + } + cJSON *jParam = cJSON_Parse(result.c_str()); + CHECK_NULL_VOID(jParam); + if (!CJsonParamCheck(jParam, { KEY_DEV_ID, KEY_DH_ID })) { + DHLOGE("Not found the keys."); + cJSON_Delete(jParam); + return; + } + mgrCallback_->OnEnableAudioResult(std::string(cJSON_GetObjectItem(jParam, KEY_DEV_ID)->valuestring), + std::string(cJSON_GetObjectItem(jParam, KEY_DH_ID)->valuestring), resultCode); + cJSON_Delete(jParam); +} + +int32_t DAudioSourceDev::TaskDisableDAudio(const std::string &args) +{ + DHLOGI("Task disable daudio."); + if (args.length() > DAUDIO_MAX_JSON_LEN || args.empty()) { + return ERR_DH_AUDIO_SA_PARAM_INVALID; + } + cJSON *jParam = cJSON_Parse(args.c_str()); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + int32_t dhId = ParseDhidFromEvent(args); + CHECK_AND_FREE_RETURN_RET_LOG(dhId == -1, ERR_DH_AUDIO_NULLPTR, jParam, + "%{public}s", "Parse dhId error."); + cJSON_Delete(jParam); + DHLOGI("Parsed dhId = %{public}d", dhId); + switch (GetDevTypeByDHId(dhId)) { + case AUDIO_DEVICE_TYPE_SPEAKER: + return DisableDSpeaker(dhId); + case AUDIO_DEVICE_TYPE_MIC: + return DisableDMic(dhId); + default: + DHLOGE("Unknown audio device. hdId: %{public}d.", dhId); + return ERR_DH_AUDIO_NOT_SUPPORT; + } +} + +int32_t DAudioSourceDev::DisableDSpeaker(const int32_t dhId) +{ + std::lock_guard devLck(ioDevMtx_); + if (deviceMap_.find(dhId) == deviceMap_.end()) { + DHLOGI("The speaker device is already disabled."); + return DH_SUCCESS; + } + auto ioDev = deviceMap_[dhId]; + CHECK_NULL_RETURN(ioDev, ERR_DH_AUDIO_NULLPTR); + return ioDev->DisableDevice(dhId); +} + +int32_t DAudioSourceDev::DisableDMic(const int32_t dhId) +{ + std::lock_guard devLck(ioDevMtx_); + if (deviceMap_.find(dhId) == deviceMap_.end()) { + DHLOGI("The mic device is already disabled."); + return DH_SUCCESS; + } + auto ioDev = deviceMap_[dhId]; + CHECK_NULL_RETURN(ioDev, ERR_DH_AUDIO_NULLPTR); + return ioDev->DisableDevice(dhId); +} + +void DAudioSourceDev::OnDisableTaskResult(int32_t resultCode, const std::string &result, const std::string &funcName) +{ + (void)funcName; + DHLOGI("On disable task result."); + CHECK_NULL_VOID(mgrCallback_); + if (result.length() > DAUDIO_MAX_JSON_LEN || result.empty()) { + return; + } + cJSON *jParam = cJSON_Parse(result.c_str()); + CHECK_NULL_VOID(jParam); + if (!CJsonParamCheck(jParam, { KEY_DEV_ID, KEY_DH_ID })) { + DHLOGE("Not found the keys."); + cJSON_Delete(jParam); + return; + } + mgrCallback_->OnDisableAudioResult(std::string(cJSON_GetObjectItem(jParam, KEY_DEV_ID)->valuestring), + std::string(cJSON_GetObjectItem(jParam, KEY_DH_ID)->valuestring), resultCode); + cJSON_Delete(jParam); +} + +int32_t DAudioSourceDev::TaskOpenDSpeaker(const std::string &args) +{ + DAudioHitrace trace("DAudioSourceDev::TaskOpenDSpeaker"); + DHLOGI("Task open speaker args: %{public}s.", args.c_str()); + if (args.length() > DAUDIO_MAX_JSON_LEN || args.empty()) { + DHLOGE("args length error. 0 or max."); + return ERR_DH_AUDIO_SA_PARAM_INVALID; + } + int32_t dhId = ParseDhidFromEvent(args); + if (dhId < 0) { + DHLOGE("Failed to parse dhardware id."); + return ERR_DH_AUDIO_FAILED; + } + auto speaker = FindIoDevImpl(args); + if (speaker == nullptr) { + DHLOGE("The IO device is invaild."); + NotifyHDF(NOTIFY_OPEN_SPEAKER_RESULT, HDF_EVENT_RESULT_FAILED, dhId); + return ERR_DH_AUDIO_NULLPTR; + } + int32_t ret = speaker->InitSenderEngine(DAudioSourceManager::GetInstance().getSenderProvider()); + if (ret != DH_SUCCESS) { + DHLOGE("Speaker init sender Engine, error code %{public}d.", ret); + NotifyHDF(NOTIFY_OPEN_SPEAKER_RESULT, HDF_EVENT_INIT_ENGINE_FAILED, dhId); + return ret; + } + + cJSON *jAudioParam = cJSON_CreateObject(); + CHECK_NULL_RETURN(jAudioParam, ERR_DH_AUDIO_NULLPTR); + to_json(jAudioParam, speaker->GetAudioParam()); + std::string dhIdString = std::to_string(dhId); + ret = NotifySinkDev(OPEN_SPEAKER, jAudioParam, dhIdString); + if (ret != DH_SUCCESS) { + DHLOGE("Notify sink open speaker failed, error code %{public}d.", ret); + cJSON_Delete(jAudioParam); + NotifyHDF(NOTIFY_OPEN_SPEAKER_RESULT, HDF_EVENT_NOTIFY_SINK_FAILED, dhId); + return ret; + } + ret = OpenDSpeakerInner(speaker, dhId); + if (ret != DH_SUCCESS) { + cJSON_Delete(jAudioParam); + DHLOGE("Task Open DSpeaker Execute failed, error code %{public}d.", ret); + return ret; + } + cJSON_Delete(jAudioParam); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::ParseDhidFromEvent(std::string args) +{ + DHLOGI("ParseDhidFrom args : %{public}s", args.c_str()); + cJSON *jParam = cJSON_Parse(args.c_str()); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_FAILED); + if (!CJsonParamCheck(jParam, { KEY_DH_ID })) { + DHLOGE("Not found the keys of dhId."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_FAILED; + } + cJSON *dhIdItem = cJSON_GetObjectItem(jParam, KEY_DH_ID); + if (dhIdItem == NULL || !cJSON_IsString(dhIdItem)) { + DHLOGE("Not found the keys of dhId."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_FAILED; + } + int32_t dhId = ConvertString2Int(std::string(dhIdItem->valuestring)); + cJSON_Delete(jParam); + DHLOGI("Parsed dhId is: %{public}d.", dhId); + return dhId; +} + +int32_t DAudioSourceDev::ConvertString2Int(std::string val) +{ + if (!CheckIsNum(val)) { + DHLOGE("String is not number. str:%{public}s.", val.c_str()); + return ERR_DH_AUDIO_FAILED; + } + return std::stoi(val); +} + +int32_t DAudioSourceDev::OpenDSpeakerInner(std::shared_ptr &speaker, const int32_t dhId) +{ + int32_t ret = speaker->SetUp(); + if (ret != DH_SUCCESS) { + DHLOGE("Speaker setup failed, error code %{public}d.", ret); + NotifyHDF(NOTIFY_OPEN_SPEAKER_RESULT, HDF_EVENT_TRANS_SETUP_FAILED, dhId); + return ret; + } + ret = speaker->Start(); + if (ret != DH_SUCCESS) { + DHLOGE("Speaker start failed, error code %{public}d.", ret); + speaker->Stop(); + speaker->Release(); + NotifyHDF(NOTIFY_OPEN_SPEAKER_RESULT, HDF_EVENT_TRANS_START_FAILED, dhId); + return ret; + } + NotifyHDF(NOTIFY_OPEN_SPEAKER_RESULT, HDF_EVENT_RESULT_SUCCESS, dhId); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::CloseSpkNew(const std::string &args) +{ + DHLOGI("Close speaker new"); + cJSON *jAudioParam = nullptr; + int32_t dhId = ParseDhidFromEvent(args); + CHECK_AND_RETURN_RET_LOG(dhId == -1, ERR_DH_AUDIO_NULLPTR, + "%{public}s", "Parse dhId error."); + NotifySinkDev(CLOSE_SPEAKER, jAudioParam, std::to_string(dhId)); + bool closeStatus = true; + auto speaker = FindIoDevImpl(args); + CHECK_NULL_RETURN(speaker, ERR_DH_AUDIO_NULLPTR); + if (speaker->Stop() != DH_SUCCESS) { + DHLOGE("Speaker stop failed."); + closeStatus = false; + } + if (speaker->Release() != DH_SUCCESS) { + DHLOGE("Speaker release failed."); + closeStatus = false; + } + if (!closeStatus) { + return ERR_DH_AUDIO_FAILED; + } + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::TaskCloseDSpeaker(const std::string &args) +{ + DHLOGI("Task close speaker, args: %{public}s.", args.c_str()); + int32_t dhId = ParseDhidFromEvent(args); + if (dhId < 0) { + DHLOGE("Failed to parse dhardware id."); + return ERR_DH_AUDIO_FAILED; + } + auto speaker = FindIoDevImpl(args); + if (speaker == nullptr) { + DHLOGE("Speaker already closed."); + NotifyHDF(NOTIFY_CLOSE_SPEAKER_RESULT, HDF_EVENT_RESULT_SUCCESS, dhId); + return DH_SUCCESS; + } + if (args.length() > DAUDIO_MAX_JSON_LEN || args.empty()) { + DHLOGE("args length error."); + NotifyHDF(NOTIFY_CLOSE_SPEAKER_RESULT, HDF_EVENT_RESULT_FAILED, dhId); + return ERR_DH_AUDIO_SA_PARAM_INVALID; + } + int32_t ret = CloseSpkNew(args); + if (ret != DH_SUCCESS) { + DHLOGE("Close spk failed."); + NotifyHDF(NOTIFY_CLOSE_SPEAKER_RESULT, HDF_EVENT_RESULT_FAILED, dhId); + return ret; + } + NotifyHDF(NOTIFY_CLOSE_SPEAKER_RESULT, HDF_EVENT_RESULT_SUCCESS, dhId); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::TaskOpenDMic(const std::string &args) +{ + DHLOGI("Task open mic, args: %{public}s.", args.c_str()); + if (args.length() > DAUDIO_MAX_JSON_LEN || args.empty()) { + return ERR_DH_AUDIO_SA_PARAM_INVALID; + } + int32_t dhId = ParseDhidFromEvent(args); + CHECK_AND_RETURN_RET_LOG(dhId < 0, ERR_DH_AUDIO_FAILED, "%{public}s", "Failed to parse dhardware id."); + auto mic = FindIoDevImpl(args); + if (mic == nullptr) { + DHLOGE("Mic device not init"); + NotifyHDF(NOTIFY_OPEN_MIC_RESULT, HDF_EVENT_RESULT_FAILED, dhId); + return ERR_DH_AUDIO_NULLPTR; + } + int32_t ret = mic->InitReceiverEngine(DAudioSourceManager::GetInstance().getReceiverProvider()); + if (ret != DH_SUCCESS) { + DHLOGE("Init receiver engine failed."); + NotifyHDF(NOTIFY_OPEN_MIC_RESULT, HDF_EVENT_INIT_ENGINE_FAILED, dhId); + return ret; + } + ret = mic->SetUp(); + if (ret != DH_SUCCESS) { + DHLOGE("Mic setup failed."); + NotifyHDF(NOTIFY_OPEN_MIC_RESULT, HDF_EVENT_TRANS_SETUP_FAILED, dhId); + return ret; + } + + cJSON *jAudioParam = cJSON_CreateObject(); + CHECK_NULL_RETURN(jAudioParam, ERR_DH_AUDIO_NULLPTR); + to_json(jAudioParam, mic->GetAudioParam()); + ret = NotifySinkDev(OPEN_MIC, jAudioParam, std::to_string(dhId)); + if (ret != DH_SUCCESS) { + DHLOGE("Notify sink open mic failed, error code %{public}d.", ret); + mic->Release(); + NotifyHDF(NOTIFY_OPEN_MIC_RESULT, HDF_EVENT_NOTIFY_SINK_FAILED, dhId); + cJSON_Delete(jAudioParam); + return ret; + } + + ret = mic->Start(); + if (ret != DH_SUCCESS) { + DHLOGE("Mic start failed, error code %{public}d.", ret); + mic->Stop(); + mic->Release(); + NotifyHDF(NOTIFY_OPEN_MIC_RESULT, HDF_EVENT_TRANS_START_FAILED, dhId); + cJSON_Delete(jAudioParam); + return ret; + } + NotifyHDF(NOTIFY_OPEN_MIC_RESULT, HDF_EVENT_RESULT_SUCCESS, dhId); + cJSON_Delete(jAudioParam); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::CloseMicNew(const std::string &args) +{ + DHLOGI("Close mic new."); + cJSON *jAudioParam = nullptr; + int32_t dhId = ParseDhidFromEvent(args); + CHECK_AND_RETURN_RET_LOG(dhId == -1, ERR_DH_AUDIO_NULLPTR, + "%{public}s", "Parse dhId error."); + NotifySinkDev(CLOSE_MIC, jAudioParam, std::to_string(dhId)); + + auto mic = FindIoDevImpl(args); + CHECK_NULL_RETURN(mic, DH_SUCCESS); + if (mic->Stop() != DH_SUCCESS || mic->Release() != DH_SUCCESS) { + return ERR_DH_AUDIO_FAILED; + } + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::TaskCloseDMic(const std::string &args) +{ + DHLOGI("Task close mic, args: %{public}s.", args.c_str()); + if (args.length() > DAUDIO_MAX_JSON_LEN || args.empty()) { + DHLOGE("Args length err. 0 or max."); + return ERR_DH_AUDIO_SA_PARAM_INVALID; + } + int32_t dhId = ParseDhidFromEvent(args); + if (dhId < 0) { + DHLOGE("Failed to parse dhardware id."); + return ERR_DH_AUDIO_FAILED; + } + auto mic = FindIoDevImpl(args); + if (mic == nullptr) { + DHLOGE("Mic device already closed."); + NotifyHDF(NOTIFY_CLOSE_MIC_RESULT, HDF_EVENT_RESULT_SUCCESS, dhId); + return DH_SUCCESS; + } + int32_t ret = CloseMicNew(args); + if (ret != DH_SUCCESS) { + DHLOGE("Task close mic error."); + NotifyHDF(NOTIFY_CLOSE_MIC_RESULT, HDF_EVENT_RESULT_FAILED, dhId); + return ret; + } + NotifyHDF(NOTIFY_CLOSE_MIC_RESULT, HDF_EVENT_RESULT_SUCCESS, dhId); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::TaskDMicClosed(const std::string &args) +{ + DHLOGI("Task dmic closed, args: %{public}s.", args.c_str()); + if (args.length() > DAUDIO_MAX_JSON_LEN || args.empty()) { + DHLOGE("Args length err. 0 or max."); + return ERR_DH_AUDIO_SA_PARAM_INVALID; + } + int32_t dhId = ParseDhidFromEvent(args); + if (dhId < 0) { + DHLOGE("Failed to parse dhardware id."); + return ERR_DH_AUDIO_FAILED; + } + auto mic = FindIoDevImpl(args); + CHECK_NULL_RETURN(mic, DH_SUCCESS); + AudioEvent event(MIC_CLOSED, args); + return mic->NotifyHdfAudioEvent(event, dhId); +} + +int32_t DAudioSourceDev::TaskSetVolume(const std::string &args) +{ + DHLOGD("Task set volume, args: %{public}s.", args.c_str()); + AudioEvent event(getEventTypeFromArgs(args), args); + return SendAudioEventToRemote(event); +} + +int32_t DAudioSourceDev::TaskChangeVolume(const std::string &args) +{ + DHLOGD("Task change volume, args: %{public}s.", args.c_str()); + cJSON *jParam = cJSON_Parse(args.c_str()); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + if (!CJsonParamCheck(jParam, { KEY_DH_ID })) { + DHLOGE("Not found the keys of dhId."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_FAILED; + } + cJSON *dhIdItem = cJSON_GetObjectItem(jParam, KEY_DH_ID); + if (dhIdItem == NULL || !cJSON_IsString(dhIdItem)) { + DHLOGE("Not found the keys of dhId."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_FAILED; + } + int32_t dhId = ConvertString2Int(std::string(dhIdItem->valuestring)); + cJSON_Delete(jParam); + return NotifyHDF(AudioEventType::VOLUME_CHANGE, args, dhId); +} + +int32_t DAudioSourceDev::TaskChangeFocus(const std::string &args) +{ + DHLOGD("Task change focus, args: %{public}s.", args.c_str()); + int32_t dhId = ParseDhidFromEvent(args); + if (dhId < 0) { + DHLOGE("Failed to parse dhardware id."); + return ERR_DH_AUDIO_FAILED; + } + return NotifyHDF(AudioEventType::AUDIO_FOCUS_CHANGE, args, dhId); +} + +int32_t DAudioSourceDev::TaskChangeRenderState(const std::string &args) +{ + DHLOGD("Task change render state, args: %{public}s.", args.c_str()); + cJSON *jParam = cJSON_Parse(args.c_str()); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + + if (!CJsonParamCheck(jParam, { KEY_DH_ID })) { + DHLOGE("Not found the keys of dhId."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_FAILED; + } + cJSON *dhIdItem = cJSON_GetObjectItem(jParam, KEY_DH_ID); + if (dhIdItem == NULL || !cJSON_IsString(dhIdItem)) { + DHLOGE("Not found the keys of dhId."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_FAILED; + } + int32_t dhId = ConvertString2Int(std::string(dhIdItem->valuestring)); + cJSON_Delete(jParam); + return NotifyHDF(AudioEventType::AUDIO_RENDER_STATE_CHANGE, args, dhId); +} + +int32_t DAudioSourceDev::TaskPlayStatusChange(const std::string &args) +{ + DHLOGD("Task play status change, content: %{public}s.", args.c_str()); + AudioEvent audioEvent(CHANGE_PLAY_STATUS, args); + if (SendAudioEventToRemote(audioEvent) != DH_SUCCESS) { + DHLOGE("Task Play status change failed."); + return ERR_DH_AUDIO_FAILED; + } + auto speaker = FindIoDevImpl(args); + CHECK_NULL_RETURN(speaker, ERR_DH_AUDIO_NULLPTR); + + std::string changeType = ParseStringFromArgs(args, KEY_CHANGE_TYPE); + if (changeType == AUDIO_EVENT_RESTART) { + if (speaker->Restart() != DH_SUCCESS) { + DHLOGE("Speaker restart failed."); + } + return ERR_DH_AUDIO_FAILED; + } else if (changeType == AUDIO_EVENT_PAUSE) { + if (speaker->Pause() != DH_SUCCESS) { + DHLOGE("Speaker Pause failed."); + } + return ERR_DH_AUDIO_FAILED; + } else { + DHLOGE("Play status error."); + return ERR_DH_AUDIO_FAILED; + } +} + +int32_t DAudioSourceDev::SendAudioEventToRemote(const AudioEvent &event) +{ + // because: type: CHANGE_PLAY_STATUS / VOLUME_MUTE_SET / VOLUME_SET, so speaker + std::shared_ptr speaker = nullptr; + if (event.type == VOLUME_SET) { + int32_t dhId = 0; + if (GetAudioParamInt(event.content, "dhId", dhId) != DH_SUCCESS) { + DHLOGE("Get key of dhId failed."); + return ERR_DH_AUDIO_FAILED; + } + std::lock_guard devLck(ioDevMtx_); + speaker = deviceMap_[dhId]; + } else { + speaker = FindIoDevImpl(event.content); + } + + CHECK_NULL_RETURN(speaker, ERR_DH_AUDIO_NULLPTR); + int32_t ret = speaker->SendMessage(static_cast(event.type), + event.content, devId_); + if (ret != DH_SUCCESS) { + DHLOGE("Task send message to remote failed."); + return ERR_DH_AUDIO_NULLPTR; + } + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::TaskSpkMmapStart(const std::string &args) +{ + DHLOGI("Task spk mmap start, content: %{public}s.", args.c_str()); + auto speaker = FindIoDevImpl(args); + CHECK_NULL_RETURN(speaker, ERR_DH_AUDIO_NULLPTR); + int32_t ret = speaker->MmapStart(); + if (ret != DH_SUCCESS) { + DHLOGE("Task spk mmap start fail, error code: %{public}d.", ret); + } + return ret; +} + +int32_t DAudioSourceDev::TaskSpkMmapStop(const std::string &args) +{ + DHLOGI("Task spk mmap stop, content: %{public}s.", args.c_str()); + auto speaker = FindIoDevImpl(args); + CHECK_NULL_RETURN(speaker, ERR_DH_AUDIO_NULLPTR); + speaker->MmapStop(); + return DH_SUCCESS; +} + +int32_t DAudioSourceDev::TaskMicMmapStart(const std::string &args) +{ + DHLOGI("Task mic mmap start, content: %{public}s.", args.c_str()); + auto mic = FindIoDevImpl(args); + CHECK_NULL_RETURN(mic, ERR_DH_AUDIO_NULLPTR); + int32_t ret = mic->MmapStart(); + if (ret != DH_SUCCESS) { + DHLOGE("Task mic mmap start fail, error code: %{public}d.", ret); + } + return ret; +} + +int32_t DAudioSourceDev::TaskMicMmapStop(const std::string &args) +{ + DHLOGI("Task mic mmap stop, content: %{public}s.", args.c_str()); + auto mic = FindIoDevImpl(args); + CHECK_NULL_RETURN(mic, ERR_DH_AUDIO_NULLPTR); + mic->MmapStop(); + return DH_SUCCESS; +} + +void DAudioSourceDev::OnTaskResult(int32_t resultCode, const std::string &result, const std::string &funcName) +{ + (void)resultCode; + (void)result; + (void)funcName; + DHLOGD("OnTaskResult. resultcode: %{public}d, result: %{public}s, funcName: %{public}s", resultCode, result.c_str(), + funcName.c_str()); +} + +int32_t DAudioSourceDev::NotifySinkDev(const AudioEventType type, const cJSON *Param, const std::string dhId) +{ + if (!isRpcOpen_.load()) { + DHLOGE("Network connection failure, rpc is not open!"); + return ERR_DH_AUDIO_FAILED; + } + + std::random_device rd; + const uint32_t randomTaskCode = rd(); + constexpr uint32_t eventOffset = 4; + cJSON *jParam = cJSON_CreateObject(); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + cJSON_AddStringToObject(jParam, KEY_DH_ID, dhId.c_str()); + cJSON_AddNumberToObject(jParam, KEY_EVENT_TYPE, static_cast(type)); + cJSON *jParamCopy = cJSON_Duplicate(Param, 1); + cJSON_AddItemToObject(jParam, KEY_AUDIO_PARAM, jParamCopy); + cJSON_AddStringToObject(jParam, KEY_RANDOM_TASK_CODE, std::to_string(randomTaskCode).c_str()); + DHLOGD("Notify sink dev, new engine, random task code:%{public}s", std::to_string(randomTaskCode).c_str()); + + std::lock_guard devLck(ioDevMtx_); + int32_t dhIdInt = ConvertString2Int(dhId); + if (deviceMap_.find(dhIdInt) == deviceMap_.end()) { + DHLOGE("speaker or mic dev is null. find index: %{public}d.", dhIdInt); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NULLPTR; + } + auto ioDev = deviceMap_[dhIdInt]; + if (type == OPEN_CTRL || type == CLOSE_CTRL) { + DHLOGE("In new engine mode, ctrl is not allowed."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NULLPTR; + } + char *content = cJSON_PrintUnformatted(jParam); + if (content == nullptr) { + DHLOGE("Failed to create JSON data"); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NULLPTR; + } + ioDev->SendMessage(static_cast(type), std::string(content), devId_); + if (type == CLOSE_SPEAKER || type == CLOSE_MIC) { + // Close spk || Close mic do not need to wait RPC + cJSON_Delete(jParam); + cJSON_free(content); + return DH_SUCCESS; + } + cJSON_Delete(jParam); + cJSON_free(content); + return WaitForRPC(static_cast(static_cast(type) + eventOffset)); +} + +int32_t DAudioSourceDev::NotifyHDF(const AudioEventType type, const std::string result, const int32_t dhId) +{ + DHLOGI("Notify HDF framework the result, event type: %{public}d; result: %{public}s.", type, result.c_str()); + std::lock_guard devLck(ioDevMtx_); + if (deviceMap_.find(dhId) == deviceMap_.end()) { + DHLOGE("Speaker or mic dev is null. dhId: %{public}d", dhId); + return ERR_DH_AUDIO_NULLPTR; + } + auto ioDev = deviceMap_[dhId]; + AudioEvent event(type, result); + switch (type) { + case NOTIFY_OPEN_SPEAKER_RESULT: + case NOTIFY_CLOSE_SPEAKER_RESULT: + case VOLUME_CHANGE: + case AUDIO_FOCUS_CHANGE: + case AUDIO_RENDER_STATE_CHANGE: + return ioDev->NotifyHdfAudioEvent(event, dhId); + case NOTIFY_OPEN_MIC_RESULT: + case NOTIFY_CLOSE_MIC_RESULT: + return ioDev->NotifyHdfAudioEvent(event, dhId); + default: + DHLOGE("NotifyHDF unknown type."); + return ERR_DH_AUDIO_FAILED; + } + return DH_SUCCESS; +} + +AudioEventType DAudioSourceDev::getEventTypeFromArgs(const std::string &args) +{ + std::string::size_type volume_mute_set = args.find(STREAM_MUTE_STATUS); + if (volume_mute_set != std::string::npos) { + return AudioEventType::VOLUME_MUTE_SET; + } + return AudioEventType::VOLUME_SET; +} + +void DAudioSourceDev::to_json(cJSON *j, const AudioParam ¶m) +{ + CHECK_NULL_VOID(j); + cJSON_AddNumberToObject(j, KEY_SAMPLING_RATE, param.comParam.sampleRate); + cJSON_AddNumberToObject(j, KEY_FORMAT, param.comParam.bitFormat); + cJSON_AddNumberToObject(j, KEY_CHANNELS, param.comParam.channelMask); + cJSON_AddNumberToObject(j, KEY_FRAMESIZE, param.comParam.frameSize); + cJSON_AddNumberToObject(j, KEY_CONTENT_TYPE, param.renderOpts.contentType); + cJSON_AddNumberToObject(j, KEY_STREAM_USAGE, param.renderOpts.streamUsage); + cJSON_AddNumberToObject(j, KEY_RENDER_FLAGS, param.renderOpts.renderFlags); + cJSON_AddNumberToObject(j, KEY_CAPTURE_FLAGS, param.captureOpts.capturerFlags); + cJSON_AddNumberToObject(j, KEY_SOURCE_TYPE, param.captureOpts.sourceType); +} + +DAudioSourceDev::SourceEventHandler::SourceEventHandler(const std::shared_ptr &runner, + const std::shared_ptr &dev) : AppExecFwk::EventHandler(runner), sourceDev_(dev) +{ + DHLOGD("Event handler is constructing."); + mapEventFuncs_[EVENT_DAUDIO_ENABLE] = &DAudioSourceDev::SourceEventHandler::EnableDAudioCallback; + mapEventFuncs_[EVENT_DAUDIO_DISABLE] = &DAudioSourceDev::SourceEventHandler::DisableDAudioCallback; + mapEventFuncs_[EVENT_OPEN_SPEAKER] = &DAudioSourceDev::SourceEventHandler::OpenDSpeakerCallback; + mapEventFuncs_[EVENT_CLOSE_SPEAKER] = &DAudioSourceDev::SourceEventHandler::CloseDSpeakerCallback; + mapEventFuncs_[EVENT_OPEN_MIC] = &DAudioSourceDev::SourceEventHandler::OpenDMicCallback; + mapEventFuncs_[EVENT_CLOSE_MIC] = &DAudioSourceDev::SourceEventHandler::CloseDMicCallback; + mapEventFuncs_[EVENT_DMIC_CLOSED] = &DAudioSourceDev::SourceEventHandler::DMicClosedCallback; + mapEventFuncs_[EVENT_VOLUME_SET] = &DAudioSourceDev::SourceEventHandler::SetVolumeCallback; + mapEventFuncs_[EVENT_VOLUME_CHANGE] = &DAudioSourceDev::SourceEventHandler::ChangeVolumeCallback; + mapEventFuncs_[EVENT_AUDIO_FOCUS_CHANGE] = &DAudioSourceDev::SourceEventHandler::ChangeFocusCallback; + mapEventFuncs_[EVENT_AUDIO_RENDER_STATE_CHANGE] = &DAudioSourceDev::SourceEventHandler::ChangeRenderStateCallback; + mapEventFuncs_[EVENT_CHANGE_PLAY_STATUS] = &DAudioSourceDev::SourceEventHandler::PlayStatusChangeCallback; + mapEventFuncs_[EVENT_MMAP_SPK_START] = &DAudioSourceDev::SourceEventHandler::SpkMmapStartCallback; + mapEventFuncs_[EVENT_MMAP_SPK_STOP] = &DAudioSourceDev::SourceEventHandler::SpkMmapStopCallback; + mapEventFuncs_[EVENT_MMAP_MIC_START] = &DAudioSourceDev::SourceEventHandler::MicMmapStartCallback; + mapEventFuncs_[EVENT_MMAP_MIC_STOP] = &DAudioSourceDev::SourceEventHandler::MicMmapStopCallback; + mapEventFuncs_[EVENT_SET_THREAD_STATUS] = &DAudioSourceDev::SourceEventHandler::SetThreadStatusFlagTrue; +} + +DAudioSourceDev::SourceEventHandler::~SourceEventHandler() {} + +void DAudioSourceDev::SourceEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) +{ + auto iter = mapEventFuncs_.find(event->GetInnerEventId()); + if (iter == mapEventFuncs_.end()) { + DHLOGE("Event Id is invaild. %{public}d", event->GetInnerEventId()); + return; + } + SourceEventFunc &func = iter->second; + (this->*func)(event); +} + +void DAudioSourceDev::SourceEventHandler::EnableDAudioCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + CHECK_NULL_VOID(event); + auto jsonString = event->GetSharedObject().get(); + CHECK_NULL_VOID(jsonString); + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskEnableDAudio(*jsonString) != DH_SUCCESS) { + DHLOGE("Open ctrl channel failed."); + } +} + +void DAudioSourceDev::SourceEventHandler::DisableDAudioCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + CHECK_NULL_VOID(event); + auto jsonString = event->GetSharedObject().get(); + CHECK_NULL_VOID(jsonString); + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskDisableDAudio(*jsonString) != DH_SUCCESS) { + DHLOGE("Disable distributed audio failed."); + } +} + +void DAudioSourceDev::SourceEventHandler::OpenDSpeakerCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskOpenDSpeaker(eventParam) != DH_SUCCESS) { + DHLOGE("Open speaker failed."); + return; + } + DHLOGI("Open speaker successfully."); +} + +void DAudioSourceDev::SourceEventHandler::CloseDSpeakerCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskCloseDSpeaker(eventParam) != DH_SUCCESS) { + DHLOGE("Close speaker failed."); + return; + } + DHLOGI("Close speaker successfully."); +} + +void DAudioSourceDev::SourceEventHandler::OpenDMicCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskOpenDMic(eventParam) != DH_SUCCESS) { + DHLOGE("Open mic failed."); + return; + } + DHLOGI("Open mic successfully."); +} + +void DAudioSourceDev::SourceEventHandler::CloseDMicCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskCloseDMic(eventParam) != DH_SUCCESS) { + DHLOGE("Close mic failed."); + return; + } + DHLOGI("Close mic successfully."); +} + +void DAudioSourceDev::SourceEventHandler::DMicClosedCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskDMicClosed(eventParam) != DH_SUCCESS) { + DHLOGE("Deal dmic closed failed."); + return; + } + DHLOGI("Deal dmic closed successfully."); +} + +void DAudioSourceDev::SourceEventHandler::SetVolumeCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskSetVolume(eventParam) != DH_SUCCESS) { + DHLOGE("Set volume failed."); + return; + } + DHLOGI("Set audio volume successfully."); +} + +void DAudioSourceDev::SourceEventHandler::ChangeVolumeCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskChangeVolume(eventParam) != DH_SUCCESS) { + DHLOGE("Failed to process volume change event."); + return; + } + DHLOGI("Processing volume change event successfully."); +} + +void DAudioSourceDev::SourceEventHandler::ChangeFocusCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskChangeFocus(eventParam) != DH_SUCCESS) { + DHLOGE("Failed to process focus change event."); + return; + } + DHLOGI("Processing volume change event successfully."); +} + +void DAudioSourceDev::SourceEventHandler::ChangeRenderStateCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskChangeRenderState(eventParam) != DH_SUCCESS) { + DHLOGE("Failed to process render state change event."); + return; + } + DHLOGI("Processing render state change event successfully."); +} + +void DAudioSourceDev::SourceEventHandler::PlayStatusChangeCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskPlayStatusChange(eventParam) != DH_SUCCESS) { + DHLOGE("Failed to process playing status change event."); + return; + } + DHLOGI("Processing playing status change event successfully."); +} + +void DAudioSourceDev::SourceEventHandler::SpkMmapStartCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskSpkMmapStart(eventParam) != DH_SUCCESS) { + DHLOGE("Failed to start speaker with mmap mode."); + return; + } + DHLOGI("Start speaker with mmap mode successfully."); +} + +void DAudioSourceDev::SourceEventHandler::SpkMmapStopCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskSpkMmapStop(eventParam) != DH_SUCCESS) { + DHLOGE("Failed to stop speaker with mmap mode."); + return; + } + DHLOGI("Stop speaker with mmap mode successfully."); +} + +void DAudioSourceDev::SourceEventHandler::MicMmapStartCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskMicMmapStart(eventParam) != DH_SUCCESS) { + DHLOGE("Failed to start mic with mmap mode."); + return; + } + DHLOGI("Start mic with mmap mode successfully."); +} + +void DAudioSourceDev::SourceEventHandler::MicMmapStopCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + if (sourceDevObj->TaskMicMmapStop(eventParam) != DH_SUCCESS) { + DHLOGE("Failed to stop mic with mmap mode."); + return; + } + DHLOGI("Stop mic with mmap mode successfully."); +} + +void DAudioSourceDev::SourceEventHandler::SetThreadStatusFlagTrue(const AppExecFwk::InnerEvent::Pointer &event) +{ + (void) event; + auto sourceDevObj = sourceDev_.lock(); + CHECK_NULL_VOID(sourceDevObj); + sourceDevObj->threadStatusFlag_ = true; +} + +int32_t DAudioSourceDev::SourceEventHandler::GetEventParam(const AppExecFwk::InnerEvent::Pointer &event, + std::string &eventParam) +{ + CHECK_NULL_RETURN(event, ERR_DH_AUDIO_NULLPTR); + std::shared_ptr paramObj = event->GetSharedObject(); + CHECK_NULL_RETURN(paramObj, ERR_DH_AUDIO_NULLPTR); + eventParam = paramObj->content; + return DH_SUCCESS; +} +} // namespace DistributedHardware +} // namespace OHOS diff --git a/services/audiocheck/managersource/src/daudio_source_manager.cpp b/services/audiocheck/managersource/src/daudio_source_manager.cpp new file mode 100644 index 00000000..43692e73 --- /dev/null +++ b/services/audiocheck/managersource/src/daudio_source_manager.cpp @@ -0,0 +1,611 @@ +/* + * Copyright (c) 2022-2023 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 "daudio_source_manager.h" + +#include +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "xcollie/watchdog.h" + +#include "daudio_constants.h" +#include "daudio_errorcode.h" +#include "daudio_log.h" +#include "daudio_util.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "DAudioSourceManager" + +namespace OHOS { +namespace DistributedHardware { +namespace { +constexpr uint32_t MAX_DEVICE_ID_LENGTH = 200; +constexpr uint32_t MAX_DISTRIBUTED_HARDWARE_ID_LENGTH = 100; +constexpr uint32_t EVENT_MANAGER_ENABLE_DAUDIO = 11; +constexpr uint32_t EVENT_MANAGER_DISABLE_DAUDIO = 12; +} +IMPLEMENT_SINGLE_INSTANCE(DAudioSourceManager); +using AVTransProviderClass = IAVEngineProvider *(*)(const std::string &); + +const std::string SENDER_SO_NAME = "libdistributed_av_sender.z.so"; +const std::string GET_SENDER_PROVIDER_FUNC = "GetAVSenderEngineProvider"; +const std::string RECEIVER_SO_NAME = "libdistributed_av_receiver.z.so"; +const std::string GET_RECEIVER_PROVIDER_FUNC = "GetAVReceiverEngineProvider"; +#ifdef __LP64__ +const std::string LIB_LOAD_PATH = "/system/lib64/"; +#else +const std::string LIB_LOAD_PATH = "/system/lib/"; +#endif + +DAudioSourceManager::DAudioSourceManager() +{ + DHLOGD("Distributed audio source manager constructed."); +} + +DAudioSourceManager::~DAudioSourceManager() +{ + if (devClearThread_.joinable()) { + devClearThread_.join(); + } + + isHicollieRunning_.store(false); + if (listenThread_.joinable()) { + listenThread_.join(); + } + DHLOGD("Distributed audio source manager destructed."); +} + +int32_t DAudioSourceManager::Init(const sptr &callback) +{ + DHLOGI("Init audio source manager."); + CHECK_NULL_RETURN(callback, ERR_DH_AUDIO_NULLPTR); + if (DAudioHdiHandler::GetInstance().InitHdiHandler() != DH_SUCCESS) { + DHLOGE("Init Hdi handler failed."); + return ERR_DH_AUDIO_FAILED; + } + if (GetLocalDeviceNetworkId(localDevId_) != DH_SUCCESS) { + DHLOGE("Get local network id failed."); + return ERR_DH_AUDIO_FAILED; + } + + ipcCallback_ = callback; + daudioMgrCallback_ = std::make_shared(); + int32_t ret = LoadAVSenderEngineProvider(); + if (ret != DH_SUCCESS) { + DHLOGE("load av transport sender engine provider failed"); + return ERR_DH_AUDIO_FAILED; + } + ret = LoadAVReceiverEngineProvider(); + if (ret != DH_SUCCESS) { + DHLOGE("load av transport receiver engine provider failed."); + return ERR_DH_AUDIO_FAILED; + } + if (!isHicollieRunning_.load()) { + isHicollieRunning_.store(true); + listenThread_ = std::thread(&DAudioSourceManager::ListenAudioDev, this); + if (pthread_setname_np(listenThread_.native_handle(), LISTEN_THREAD) != DH_SUCCESS) { + DHLOGE("Dev clear thread setname failed."); + } + } + // init event handler + auto runner = AppExecFwk::EventRunner::Create(true); + CHECK_NULL_RETURN(runner, ERR_DH_AUDIO_NULLPTR); + handler_ = std::make_shared(runner); + DHLOGI("Init DAudioManager successfuly."); + return DH_SUCCESS; +} + +int32_t DAudioSourceManager::UnInit() +{ + DHLOGI("Uninit audio source manager."); + UnloadAVReceiverEngineProvider(); + UnloadAVSenderEngineProvider(); + { + std::lock_guard lock(devMapMtx_); + for (auto iter = audioDevMap_.begin(); iter != audioDevMap_.end(); iter++) { + if (iter->second.dev == nullptr) { + continue; + } + iter->second.dev->SleepAudioDev(); + } + audioDevMap_.clear(); + DHLOGI("Audio dev map cleared."); + } + if (devClearThread_.joinable()) { + devClearThread_.join(); + } + + isHicollieRunning_.store(false); + if (listenThread_.joinable()) { + listenThread_.join(); + } + + ipcCallback_ = nullptr; + daudioMgrCallback_ = nullptr; + if (DAudioHdiHandler::GetInstance().UninitHdiHandler() != DH_SUCCESS) { + DHLOGE("Uninit Hdi handler failed."); + return ERR_DH_AUDIO_FAILED; + } + + CHECK_NULL_RETURN(handler_, DH_SUCCESS); + while (!handler_->IsIdle()) { + DHLOGD("manager handler is running, wait for idle."); + usleep(WAIT_HANDLER_IDLE_TIME_US); + } + DHLOGI("Uninit audio source manager exit."); + return DH_SUCCESS; +} + +static bool CheckParams(const std::string &devId, const std::string &dhId) +{ + DHLOGD("Checking params of daudio."); + if (devId.empty() || dhId.empty() || + devId.size() > MAX_DEVICE_ID_LENGTH || dhId.size() > MAX_DISTRIBUTED_HARDWARE_ID_LENGTH) { + return false; + } + return true; +} + +int32_t DAudioSourceManager::EnableDAudio(const std::string &devId, const std::string &dhId, + const std::string &version, const std::string &attrs, const std::string &reqId) +{ + DHLOGI("Enable distributed audio, devId: %{public}s, dhId: %{public}s, version: %{public}s, reqId: %{public}s.", + GetAnonyString(devId).c_str(), dhId.c_str(), version.c_str(), reqId.c_str()); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + + cJSON *jParam = cJSON_CreateObject(); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + cJSON_AddStringToObject(jParam, KEY_DEV_ID, devId.c_str()); + cJSON_AddStringToObject(jParam, KEY_DH_ID, dhId.c_str()); + cJSON_AddStringToObject(jParam, KEY_VERSION, version.c_str()); + cJSON_AddStringToObject(jParam, KEY_ATTRS, attrs.c_str()); + cJSON_AddStringToObject(jParam, KEY_REQID, reqId.c_str()); + char *jsonString = cJSON_PrintUnformatted(jParam); + if (jsonString == nullptr) { + DHLOGE("Failed to create JSON data"); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NULLPTR; + } + auto eventParam = std::make_shared(jsonString); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_MANAGER_ENABLE_DAUDIO, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + cJSON_Delete(jParam); + cJSON_free(jsonString); + return ERR_DH_AUDIO_FAILED; + } + cJSON_Delete(jParam); + cJSON_free(jsonString); + DHLOGI("Enable audio task generate successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceManager::DoEnableDAudio(const std::string &args) +{ + std::string devId = ParseStringFromArgs(args, KEY_DEV_ID); + std::string dhId = ParseStringFromArgs(args, KEY_DH_ID); + std::string version = ParseStringFromArgs(args, KEY_VERSION); + std::string attrs = ParseStringFromArgs(args, KEY_ATTRS); + std::string reqId = ParseStringFromArgs(args, KEY_REQID); + DHLOGI("Do Enable distributed audio, devId: %{public}s, dhId: %{public}s, version:%{public}s, reqId:%{public}s.", + GetAnonyString(devId).c_str(), dhId.c_str(), version.c_str(), reqId.c_str()); + if (!CheckParams(devId, dhId) || attrs.empty()) { + DHLOGE("Enable params are incorrect."); + return ERR_DH_AUDIO_FAILED; + } + std::shared_ptr sourceDev = nullptr; + { + std::lock_guard lock(devMapMtx_); + auto device = audioDevMap_.find(devId); + if (device == audioDevMap_.end()) { + if (CreateAudioDevice(devId) != DH_SUCCESS) { + return ERR_DH_AUDIO_FAILED; + } + } + audioDevMap_[devId].ports[dhId] = reqId; + sourceDev = audioDevMap_[devId].dev; + } + DHLOGI("Call source dev to enable daudio."); + int32_t result = sourceDev->EnableDAudio(dhId, attrs); + return OnEnableDAudio(devId, dhId, result); +} + +int32_t DAudioSourceManager::DisableDAudio(const std::string &devId, const std::string &dhId, const std::string &reqId) +{ + DHLOGI("Disable distributed audio, devId: %{public}s, dhId: %{public}s, reqId: %{public}s.", + GetAnonyString(devId).c_str(), dhId.c_str(), reqId.c_str()); + CHECK_NULL_RETURN(handler_, ERR_DH_AUDIO_NULLPTR); + cJSON *jParam = cJSON_CreateObject(); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + cJSON_AddStringToObject(jParam, KEY_DEV_ID, devId.c_str()); + cJSON_AddStringToObject(jParam, KEY_DH_ID, dhId.c_str()); + cJSON_AddStringToObject(jParam, KEY_REQID, reqId.c_str()); + char *jsonString = cJSON_PrintUnformatted(jParam); + if (jsonString == nullptr) { + DHLOGE("Failed to create JSON data"); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NULLPTR; + } + auto eventParam = std::make_shared(jsonString); + auto msgEvent = AppExecFwk::InnerEvent::Get(EVENT_MANAGER_DISABLE_DAUDIO, eventParam, 0); + if (!handler_->SendEvent(msgEvent, 0, AppExecFwk::EventQueue::Priority::IMMEDIATE)) { + DHLOGE("Send event failed."); + cJSON_Delete(jParam); + cJSON_free(jsonString); + return ERR_DH_AUDIO_FAILED; + } + cJSON_Delete(jParam); + cJSON_free(jsonString); + DHLOGI("Disable audio task generate successfully."); + return DH_SUCCESS; +} + +int32_t DAudioSourceManager::DoDisableDAudio(const std::string &args) +{ + std::string devId = ParseStringFromArgs(args, KEY_DEV_ID); + std::string dhId = ParseStringFromArgs(args, KEY_DH_ID); + std::string reqId = ParseStringFromArgs(args, KEY_REQID); + DHLOGI("Do Disable distributed audio, devId: %{public}s, dhId: %{public}s, reqId:%{public}s.", + GetAnonyString(devId).c_str(), dhId.c_str(), reqId.c_str()); + if (!CheckParams(devId, dhId)) { + DHLOGE("Disable params are incorrect."); + return ERR_DH_AUDIO_FAILED; + } + std::shared_ptr sourceDev = nullptr; + { + std::lock_guard lock(devMapMtx_); + auto device = audioDevMap_.find(devId); + if (device == audioDevMap_.end()) { + DHLOGE("Audio device not exist."); + return ERR_DH_AUDIO_SA_DEVICE_NOT_EXIST; + } + CHECK_NULL_RETURN(audioDevMap_[devId].dev, DH_SUCCESS); + audioDevMap_[devId].ports[dhId] = reqId; + sourceDev = audioDevMap_[devId].dev; + } + DHLOGI("Call source dev to disable daudio."); + int32_t result = sourceDev->DisableDAudio(dhId); + return OnDisableDAudio(devId, dhId, result); +} + +int32_t DAudioSourceManager::HandleDAudioNotify(const std::string &devId, const std::string &dhId, + const int32_t eventType, const std::string &eventContent) +{ + DHLOGD("Receive audio event from devId: %{public}s, event type: %{public}d. event content: %{public}s.", + GetAnonyString(devId).c_str(), eventType, eventContent.c_str()); + if (eventContent.length() > DAUDIO_MAX_JSON_LEN || eventContent.empty()) { + return ERR_DH_AUDIO_FAILED; + } + + // now ctrl channel is also goto here, please sure here not crash. + cJSON *jParam = cJSON_Parse(eventContent.c_str()); + if (CJsonParamCheck(jParam, { KEY_RANDOM_TASK_CODE })) { + DHLOGD("Receive audio notify from sink, random task code: %{public}s", + cJSON_GetObjectItemCaseSensitive(jParam, KEY_RANDOM_TASK_CODE)->valuestring); + } + + std::shared_ptr sourceDev = nullptr; + { + std::lock_guard lock(devMapMtx_); + auto device = audioDevMap_.find(devId); + if (device == audioDevMap_.end()) { + DHLOGE("Audio device not exist."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_SA_DEVICE_NOT_EXIST; + } + sourceDev = audioDevMap_[devId].dev; + } + + AudioEvent audioEvent(eventType, eventContent); + sourceDev->NotifyEvent(audioEvent); + cJSON_Delete(jParam); + return DH_SUCCESS; +} + +int32_t DAudioSourceManager::DAudioNotify(const std::string &devId, const std::string &dhId, const int32_t eventType, + const std::string &eventContent) +{ + DHLOGD("Distributed audio notify, devId: %{public}s, dhId: %{public}s, eventType: %{public}d.", + GetAnonyString(devId).c_str(), dhId.c_str(), eventType); + { + std::lock_guard lck(remoteSvrMutex_); + auto sinkProxy = sinkServiceMap_.find(devId); + if (sinkProxy != sinkServiceMap_.end()) { + if (sinkProxy->second != nullptr) { + sinkProxy->second->DAudioNotify(localDevId_, dhId, eventType, eventContent); + return DH_SUCCESS; + } + } + } + + auto samgr = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + CHECK_NULL_RETURN(samgr, ERR_DH_AUDIO_NULLPTR); + auto remoteObject = samgr->GetSystemAbility(DISTRIBUTED_HARDWARE_AUDIO_SINK_SA_ID, devId); + CHECK_NULL_RETURN(remoteObject, ERR_DH_AUDIO_NULLPTR); + sptr remoteSvrProxy = iface_cast(remoteObject); + CHECK_NULL_RETURN(remoteSvrProxy, ERR_DH_AUDIO_NULLPTR); + { + std::lock_guard lck(remoteSvrMutex_); + sinkServiceMap_[devId] = remoteSvrProxy; + remoteSvrProxy->DAudioNotify(localDevId_, dhId, eventType, eventContent); + } + return DH_SUCCESS; +} + +int32_t DAudioSourceManager::OnEnableDAudio(const std::string &devId, const std::string &dhId, const int32_t result) +{ + DHLOGI("On enable distributed audio devId: %{public}s, dhId: %{public}s, ret: %{public}d.", + GetAnonyString(devId).c_str(), dhId.c_str(), result); + std::string reqId = GetRequestId(devId, dhId); + if (reqId.empty()) { + return ERR_DH_AUDIO_FAILED; + } + if (result != DH_SUCCESS) { + DeleteAudioDevice(devId, dhId); + } + + CHECK_NULL_RETURN(ipcCallback_, ERR_DH_AUDIO_NULLPTR); + return ipcCallback_->OnNotifyRegResult(devId, dhId, reqId, result, ""); +} + +int32_t DAudioSourceManager::OnDisableDAudio(const std::string &devId, const std::string &dhId, const int32_t result) +{ + DHLOGI("On disable distributed audio devId: %{public}s, dhId: %{public}s, ret: %{public}d.", + GetAnonyString(devId).c_str(), dhId.c_str(), result); + std::string reqId = GetRequestId(devId, dhId); + if (reqId.empty()) { + return ERR_DH_AUDIO_FAILED; + } + if (result == DH_SUCCESS) { + DeleteAudioDevice(devId, dhId); + } + + CHECK_NULL_RETURN(ipcCallback_, ERR_DH_AUDIO_NULLPTR); + return ipcCallback_->OnNotifyUnregResult(devId, dhId, reqId, result, ""); +} + +int32_t DAudioSourceManager::CreateAudioDevice(const std::string &devId) +{ + DHLOGI("Create audio device."); + auto sourceDev = std::make_shared(devId, daudioMgrCallback_); + if (sourceDev->AwakeAudioDev() != DH_SUCCESS) { + DHLOGE("Create new audio device failed."); + return ERR_DH_AUDIO_FAILED; + } + AudioDevice device = { devId, sourceDev }; + audioDevMap_[devId] = device; + return DH_SUCCESS; +} + +void DAudioSourceManager::DeleteAudioDevice(const std::string &devId, const std::string &dhId) +{ + DHLOGI("Delete audio device, devId = %{public}s, dhId = %{public}s.", devId.c_str(), dhId.c_str()); + { + std::lock_guard lock(devMapMtx_); + audioDevMap_[devId].ports.erase(dhId); + if (!audioDevMap_[devId].ports.empty()) { + DHLOGI("audioDevMap_[devId].ports is not empty"); + return; + } + } + if (devClearThread_.joinable()) { + devClearThread_.join(); + } + DHLOGI("audioDevMap_[devId].ports is empty"); + devClearThread_ = std::thread(&DAudioSourceManager::ClearAudioDev, this, devId); + if (pthread_setname_np(devClearThread_.native_handle(), DEVCLEAR_THREAD) != DH_SUCCESS) { + DHLOGE("Dev clear thread setname failed."); + } +} + +std::string DAudioSourceManager::GetRequestId(const std::string &devId, const std::string &dhId) +{ + std::lock_guard lock(devMapMtx_); + auto dev = audioDevMap_.find(devId); + if (dev == audioDevMap_.end()) { + DHLOGE("Audio device not exist."); + return ""; + } + auto port = audioDevMap_[devId].ports.find(dhId); + if (port == audioDevMap_[devId].ports.end()) { + DHLOGE("Audio port not exist."); + return ""; + } + return port->second; +} + +void DAudioSourceManager::ClearAudioDev(const std::string &devId) +{ + DHLOGI("ClearAudioDev, devId = %{public}s.", GetAnonyString(devId).c_str()); + std::lock_guard lock(devMapMtx_); + if (audioDevMap_[devId].ports.empty()) { + DHLOGI("audioDevMap_[devId].ports is empty."); + CHECK_NULL_VOID(audioDevMap_[devId].dev); + audioDevMap_[devId].dev->SleepAudioDev(); + DHLOGI("back from SleepAudioDev."); + audioDevMap_.erase(devId); + } +} + +void DAudioSourceManager::RestoreThreadStatus() +{ + if (!audioDevMap_.empty()) { + for (auto &iter : audioDevMap_) { + CHECK_NULL_VOID(iter.second.dev); + iter.second.dev->RestoreThreadStatus(); + } + } +} + +void DAudioSourceManager::ListenAudioDev() +{ + auto taskFunc = [this]() { + std::lock_guard lock(devMapMtx_); + for (auto &iter : audioDevMap_) { + if (iter.second.dev->GetThreadStatusFlag()) { + iter.second.dev->SetThreadStatusFlag(); + } else { + DHLOGE("Exit the current proces"); + _Exit(0); + } + } + }; + OHOS::HiviewDFX::Watchdog::GetInstance().RunPeriodicalTask("SourceService", taskFunc, + WATCHDOG_INTERVAL_TIME, WATCHDOG_DELAY_TIME); + + while (isHicollieRunning_.load()) { + { + std::lock_guard lock(devMapMtx_); + RestoreThreadStatus(); + } + usleep(SLEEP_TIME); + } +} + +int32_t DAudioSourceManager::LoadAVSenderEngineProvider() +{ + DHLOGI("LoadAVSenderEngineProvider enter"); + char path[PATH_MAX + 1] = {0x00}; + if ((LIB_LOAD_PATH.length() + SENDER_SO_NAME.length()) > PATH_MAX || + realpath((LIB_LOAD_PATH + SENDER_SO_NAME).c_str(), path) == nullptr) { + DHLOGE("File open failed"); + return ERR_DH_AUDIO_NULLPTR; + } + pSHandler_ = dlopen(path, RTLD_LAZY | RTLD_NODELETE); + CHECK_NULL_RETURN(pSHandler_, ERR_DH_AUDIO_NULLPTR); + AVTransProviderClass getEngineFactoryFunc = (AVTransProviderClass)dlsym(pSHandler_, + GET_SENDER_PROVIDER_FUNC.c_str()); + if (getEngineFactoryFunc == nullptr) { + DHLOGE("av transport engine factory function handler is null, failed reason : %{public}s", dlerror()); + dlclose(pSHandler_); + pSHandler_ = nullptr; + return ERR_DH_AUDIO_NULLPTR; + } + sendProviderPtr_ = getEngineFactoryFunc(OWNER_NAME_D_SPEAKER); + DHLOGI("LoadAVSenderEngineProvider exit"); + return DH_SUCCESS; +} + +int32_t DAudioSourceManager::UnloadAVSenderEngineProvider() +{ + DHLOGI("UnloadAVSenderEngineProvider enter"); + if (pSHandler_ != nullptr) { + dlclose(pSHandler_); + pSHandler_ = nullptr; + } + sendProviderPtr_ = nullptr; + return DH_SUCCESS; +} + +int32_t DAudioSourceManager::LoadAVReceiverEngineProvider() +{ + DHLOGI("LoadAVReceiverEngineProvider enter"); + char path[PATH_MAX + 1] = {0x00}; + if ((LIB_LOAD_PATH.length() + RECEIVER_SO_NAME.length()) > PATH_MAX || + realpath((LIB_LOAD_PATH + RECEIVER_SO_NAME).c_str(), path) == nullptr) { + DHLOGE("File canonicalization failed"); + return ERR_DH_AUDIO_NULLPTR; + } + pRHandler_ = dlopen(path, RTLD_LAZY | RTLD_NODELETE); + CHECK_NULL_RETURN(pRHandler_, ERR_DH_AUDIO_NULLPTR); + AVTransProviderClass getEngineFactoryFunc = (AVTransProviderClass)dlsym(pRHandler_, + GET_RECEIVER_PROVIDER_FUNC.c_str()); + if (getEngineFactoryFunc == nullptr) { + DHLOGE("av transport engine factory function handler is null, failed reason : %{public}s", dlerror()); + dlclose(pRHandler_); + pRHandler_ = nullptr; + return ERR_DH_AUDIO_NULLPTR; + } + rcvProviderPtr_ = getEngineFactoryFunc(OWNER_NAME_D_MIC); + DHLOGI("LoadAVReceiverEngineProvider success"); + return DH_SUCCESS; +} + +int32_t DAudioSourceManager::UnloadAVReceiverEngineProvider() +{ + DHLOGI("UnloadAVReceiverEngineProvider"); + if (pRHandler_ != nullptr) { + dlclose(pRHandler_); + pRHandler_ = nullptr; + } + return DH_SUCCESS; +} + +IAVEngineProvider *DAudioSourceManager::getSenderProvider() +{ + return sendProviderPtr_; +} + +IAVEngineProvider *DAudioSourceManager::getReceiverProvider() +{ + return rcvProviderPtr_; +} + +DAudioSourceManager::SourceManagerHandler::SourceManagerHandler(const std::shared_ptr + &runner) : AppExecFwk::EventHandler(runner) +{ + DHLOGD("Event handler is constructing."); + mapEventFuncs_[EVENT_MANAGER_ENABLE_DAUDIO] = &DAudioSourceManager::SourceManagerHandler::EnableDAudioCallback; + mapEventFuncs_[EVENT_MANAGER_DISABLE_DAUDIO] = &DAudioSourceManager::SourceManagerHandler::DisableDAudioCallback; +} + +DAudioSourceManager::SourceManagerHandler::~SourceManagerHandler() {} + +void DAudioSourceManager::SourceManagerHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) +{ + auto iter = mapEventFuncs_.find(event->GetInnerEventId()); + if (iter == mapEventFuncs_.end()) { + DHLOGE("Event Id is invalid. %{public}d.", event->GetInnerEventId()); + return; + } + SourceManagerFunc &func = iter->second; + (this->*func)(event); +} + +void DAudioSourceManager::SourceManagerHandler::EnableDAudioCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + CHECK_NULL_VOID(event); + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + DHLOGI("Enable audio device, param:%{public}s.", eventParam.c_str()); + DAudioSourceManager::GetInstance().DoEnableDAudio(eventParam); +} + +void DAudioSourceManager::SourceManagerHandler::DisableDAudioCallback(const AppExecFwk::InnerEvent::Pointer &event) +{ + CHECK_NULL_VOID(event); + std::string eventParam; + if (GetEventParam(event, eventParam) != DH_SUCCESS) { + DHLOGE("Failed to get event parameters."); + return; + } + DHLOGI("Disable audio device, param:%{public}s.", eventParam.c_str()); + DAudioSourceManager::GetInstance().DoDisableDAudio(eventParam); +} + +int32_t DAudioSourceManager::SourceManagerHandler::GetEventParam(const AppExecFwk::InnerEvent::Pointer &event, + std::string &eventParam) +{ + CHECK_NULL_RETURN(event, ERR_DH_AUDIO_NULLPTR); + auto jsonString = event->GetSharedObject().get(); + CHECK_NULL_RETURN(jsonString, ERR_DH_AUDIO_NULLPTR); + eventParam = *jsonString; + return DH_SUCCESS; +} +} // DistributedHardware +} // OHOS diff --git a/services/audiocheck/managersource/src/daudio_source_mgr_callback.cpp b/services/audiocheck/managersource/src/daudio_source_mgr_callback.cpp new file mode 100644 index 00000000..ab68585f --- /dev/null +++ b/services/audiocheck/managersource/src/daudio_source_mgr_callback.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 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 "daudio_source_mgr_callback.h" + +#include "daudio_source_manager.h" + +namespace OHOS { +namespace DistributedHardware { +int32_t DAudioSourceMgrCallback::OnEnableAudioResult(const std::string &devId, const std::string &dhId, + const int32_t result) +{ + return DAudioSourceManager::GetInstance().OnEnableDAudio(devId, dhId, result); +} + +int32_t DAudioSourceMgrCallback::OnDisableAudioResult(const std::string &devId, const std::string &dhId, + const int32_t result) +{ + return DAudioSourceManager::GetInstance().OnDisableDAudio(devId, dhId, result); +} +} // DistributedHardware +} // OHOS \ No newline at end of file diff --git a/services/audiocheck/managersource/src/dmic_dev.cpp b/services/audiocheck/managersource/src/dmic_dev.cpp new file mode 100644 index 00000000..fc7f8545 --- /dev/null +++ b/services/audiocheck/managersource/src/dmic_dev.cpp @@ -0,0 +1,528 @@ +/* + * Copyright (c) 2022-2023 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 "dmic_dev.h" + +#include +#include +#include +#include + +#include "daudio_constants.h" +#include "daudio_errorcode.h" +#include "daudio_hidumper.h" +#include "daudio_hisysevent.h" +#include "daudio_hitrace.h" +#include "daudio_log.h" +#include "daudio_source_manager.h" +#include "daudio_util.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "DMicDev" + +namespace OHOS { +namespace DistributedHardware { +static constexpr size_t DATA_QUEUE_EXT_SIZE = 20; +void DMicDev::OnEngineTransEvent(const AVTransEvent &event) +{ + if (event.type == EventType::EVENT_START_SUCCESS) { + OnStateChange(DATA_OPENED); + } else if ((event.type == EventType::EVENT_STOP_SUCCESS) || + (event.type == EventType::EVENT_CHANNEL_CLOSED) || + (event.type == EventType::EVENT_START_FAIL)) { + OnStateChange(DATA_CLOSED); + } +} + +void DMicDev::OnEngineTransMessage(const std::shared_ptr &message) +{ + CHECK_NULL_VOID(message); + DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str()); + DAudioSourceManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_, + message->type_, message->content_); +} + +void DMicDev::OnEngineTransDataAvailable(const std::shared_ptr &audioData) +{ + DHLOGD("On Engine Data available"); + OnDecodeTransDataDone(audioData); +} + +int32_t DMicDev::InitReceiverEngine(IAVEngineProvider *providerPtr) +{ + DHLOGI("InitReceiverEngine enter."); + if (micTrans_ == nullptr) { + micTrans_ = std::make_shared(devId_, shared_from_this()); + } + int32_t ret = micTrans_->InitEngine(providerPtr); + if (ret != DH_SUCCESS) { + DHLOGE("Mic dev initialize av receiver adapter failed."); + return ret; + } + ret = micTrans_->CreateCtrl(); + if (ret != DH_SUCCESS) { + DHLOGE("Create ctrl channel failed. micdev"); + return ret; + } + return DH_SUCCESS; +} + +int32_t DMicDev::InitSenderEngine(IAVEngineProvider *providerPtr) +{ + DHLOGI("InitReceiverEngine enter."); + return DH_SUCCESS; +} + +int32_t DMicDev::EnableDevice(const int32_t dhId, const std::string &capability) +{ + DHLOGI("Enable IO device, device pin: %{public}d.", dhId); + int32_t ret = DAudioHdiHandler::GetInstance().RegisterAudioDevice(devId_, dhId, capability, shared_from_this()); + if (ret != DH_SUCCESS) { + DHLOGE("Register device failed, ret: %{public}d.", ret); + DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_REGISTER_FAIL, devId_, std::to_string(dhId), ret, + "daudio register device failed."); + return ret; + } + dhId_ = dhId; + return DH_SUCCESS; +} + +int32_t DMicDev::DisableDevice(const int32_t dhId) +{ + DHLOGI("Disable IO device, device pin: %{public}d.", dhId); + int32_t ret = DAudioHdiHandler::GetInstance().UnRegisterAudioDevice(devId_, dhId); + if (ret != DH_SUCCESS) { + DHLOGE("UnRegister failed, ret: %{public}d.", ret); + DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_UNREGISTER_FAIL, devId_, std::to_string(dhId), ret, + "daudio unregister device failed."); + return ret; + } + return DH_SUCCESS; +} + +int32_t DMicDev::OpenDevice(const std::string &devId, const int32_t dhId) +{ + DHLOGI("Open mic device devId: %{public}s, dhId: %{public}d.", GetAnonyString(devId).c_str(), dhId); + std::shared_ptr cbObj = audioEventCallback_.lock(); + CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); + + cJSON *jParam = cJSON_CreateObject(); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId).c_str()); + char *jsonData = cJSON_PrintUnformatted(jParam); + if (jsonData == nullptr) { + cJSON_Delete(jParam); + DHLOGE("Failed to create JSON data."); + return ERR_DH_AUDIO_NULLPTR; + } + std::string jsonDataStr(jsonData); + AudioEvent event(AudioEventType::OPEN_MIC, jsonDataStr); + cbObj->NotifyEvent(event); + DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_OPEN, devId, std::to_string(dhId), + "daudio mic device open success."); + cJSON_Delete(jParam); + cJSON_free(jsonData); + return DH_SUCCESS; +} + +int32_t DMicDev::CloseDevice(const std::string &devId, const int32_t dhId) +{ + DHLOGI("Close mic device devId: %{public}s, dhId: %{public}d.", GetAnonyString(devId).c_str(), dhId); + std::shared_ptr cbObj = audioEventCallback_.lock(); + CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); + + cJSON *jParam = cJSON_CreateObject(); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId).c_str()); + char *jsonData = cJSON_PrintUnformatted(jParam); + if (jsonData == nullptr) { + cJSON_Delete(jParam); + DHLOGE("Failed to create JSON data."); + return ERR_DH_AUDIO_NULLPTR; + } + std::string jsonDataStr(jsonData); + AudioEvent event(AudioEventType::CLOSE_MIC, jsonDataStr); + cbObj->NotifyEvent(event); + DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_CLOSE, devId, std::to_string(dhId), + "daudio mic device close success."); + cJSON_Delete(jParam); + cJSON_free(jsonData); + curPort_ = 0; + return DH_SUCCESS; +} + +int32_t DMicDev::SetParameters(const std::string &devId, const int32_t dhId, const AudioParamHDF ¶m) +{ + DHLOGD("Set mic parameters {samplerate: %{public}d, channelmask: %{public}d, format: %{public}d, " + "period: %{public}d, framesize: %{public}d, ext{%{public}s}}.", param.sampleRate, + param.channelMask, param.bitFormat, param.period, param.frameSize, param.ext.c_str()); + curPort_ = dhId; + paramHDF_ = param; + + param_.comParam.sampleRate = paramHDF_.sampleRate; + param_.comParam.channelMask = paramHDF_.channelMask; + param_.comParam.bitFormat = paramHDF_.bitFormat; + param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC; + param_.comParam.frameSize = paramHDF_.frameSize; + param_.captureOpts.sourceType = SOURCE_TYPE_MIC; + param_.captureOpts.capturerFlags = paramHDF_.capturerFlags; + return DH_SUCCESS; +} + +int32_t DMicDev::NotifyEvent(const std::string &devId, const int32_t dhId, const AudioEvent &event) +{ + DHLOGD("Notify mic event, type: %{public}d.", event.type); + std::shared_ptr cbObj = audioEventCallback_.lock(); + CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); + switch (event.type) { + case AudioEventType::AUDIO_START: + curStatus_ = AudioStatus::STATUS_START; + isExistedEmpty_.store(false); + break; + case AudioEventType::AUDIO_STOP: + curStatus_ = AudioStatus::STATUS_STOP; + isExistedEmpty_.store(false); + break; + default: + break; + } + AudioEvent audioEvent(event.type, event.content); + cbObj->NotifyEvent(audioEvent); + return DH_SUCCESS; +} + +int32_t DMicDev::SetUp() +{ + DHLOGI("Set up mic device."); + CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR); + int32_t ret = micTrans_->SetUp(param_, param_, shared_from_this(), CAP_MIC); + if (ret != DH_SUCCESS) { + DHLOGE("Mic trans set up failed. ret: %{public}d.", ret); + return ret; + } + return DH_SUCCESS; +} + +int32_t DMicDev::Start() +{ + DHLOGI("Start mic device."); + CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR); + int32_t ret = micTrans_->Start(); + if (ret != DH_SUCCESS) { + DHLOGE("Mic trans start failed, ret: %{public}d.", ret); + return ret; + } + std::unique_lock lck(channelWaitMutex_); + auto status = channelWaitCond_.wait_for(lck, std::chrono::seconds(CHANNEL_WAIT_SECONDS), + [this]() { return isTransReady_.load(); }); + if (!status) { + DHLOGE("Wait channel open timeout(%{public}ds).", CHANNEL_WAIT_SECONDS); + return ERR_DH_AUDIO_SA_WAIT_TIMEOUT; + } + isOpened_.store(true); + return DH_SUCCESS; +} + +int32_t DMicDev::Pause() +{ + DHLOGI("Not support."); + return DH_SUCCESS; +} + +int32_t DMicDev::Restart() +{ + DHLOGI("Not surpport."); + return DH_SUCCESS; +} + +int32_t DMicDev::Stop() +{ + DHLOGI("Stop mic device."); + CHECK_NULL_RETURN(micTrans_, DH_SUCCESS); + isOpened_.store(false); + isTransReady_.store(false); + int32_t ret = micTrans_->Stop(); + if (ret != DH_SUCCESS) { + DHLOGE("Stop mic trans failed, ret: %{public}d.", ret); + } + return DH_SUCCESS; +} + +int32_t DMicDev::Release() +{ + DHLOGI("Release mic device."); + if (ashmem_ != nullptr) { + ashmem_->UnmapAshmem(); + ashmem_->CloseAshmem(); + ashmem_ = nullptr; + DHLOGI("UnInit ashmem success."); + } + CHECK_NULL_RETURN(micTrans_, DH_SUCCESS); + + int32_t ret = micTrans_->Release(); + if (ret != DH_SUCCESS) { + DHLOGE("Release mic trans failed, ret: %{public}d.", ret); + return ret; + } + dumpFlag_.store(false); + return DH_SUCCESS; +} + +bool DMicDev::IsOpened() +{ + return isOpened_.load(); +} + +int32_t DMicDev::WriteStreamData(const std::string& devId, const int32_t dhId, std::shared_ptr &data) +{ + (void)devId; + (void)dhId; + (void)data; + return DH_SUCCESS; +} + +int32_t DMicDev::ReadStreamData(const std::string &devId, const int32_t dhId, std::shared_ptr &data) +{ + int64_t startTime = GetNowTimeUs(); + if (curStatus_ != AudioStatus::STATUS_START) { + DHLOGE("Distributed audio is not starting status."); + return ERR_DH_AUDIO_FAILED; + } + std::lock_guard lock(dataQueueMtx_); + uint32_t queSize = dataQueue_.size(); + if (insertFrameCnt_ >= queSize || queSize == 0) { + ++insertFrameCnt_; + isExistedEmpty_.store(true); + DHLOGD("Data queue is empty, count :%{public}u.", insertFrameCnt_); + data = std::make_shared(param_.comParam.frameSize); + } else { + while (insertFrameCnt_ > 0) { + DHLOGD("Data discard, count: %{public}u", insertFrameCnt_); + dataQueue_.pop(); + --insertFrameCnt_; + } + data = dataQueue_.front(); + dataQueue_.pop(); + } +#ifdef DUMP_DMICDEV_FILE + if (DaudioHidumper::GetInstance().QueryDumpDataFlag()) { + if (!dumpFlag_) { + AudioEvent event(NOTIFY_HDF_MIC_DUMP, ""); + NotifyHdfAudioEvent(event, dhId); + dumpFlag_.store(true); + } + SaveFile(MIC_DEV_FILENAME, const_cast(data->Data()), data->Size()); + } +#endif + int64_t endTime = GetNowTimeUs(); + if (IsOutDurationRange(startTime, endTime, lastReadStartTime_)) { + DHLOGE("This time read data spend: %{public}" PRId64" us, The interval of read data this time and " + "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastReadStartTime_); + } + lastReadStartTime_ = startTime; + return DH_SUCCESS; +} + +int32_t DMicDev::ReadMmapPosition(const std::string &devId, const int32_t dhId, + uint64_t &frames, CurrentTimeHDF &time) +{ + DHLOGD("Read mmap position. frames: %{public}" PRIu64", tvsec: %{public}" PRId64", tvNSec:%{public}" PRId64, + writeNum_, writeTvSec_, writeTvNSec_); + frames = writeNum_; + time.tvSec = writeTvSec_; + time.tvNSec = writeTvNSec_; + return DH_SUCCESS; +} + +int32_t DMicDev::RefreshAshmemInfo(const std::string &devId, const int32_t dhId, + int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans) +{ + DHLOGD("RefreshAshmemInfo: fd:%{public}d, ashmemLength: %{public}d, lengthPerTrans: %{public}d", + fd, ashmemLength, lengthPerTrans); + if (param_.captureOpts.capturerFlags == MMAP_MODE) { + DHLOGD("DMic dev low-latency mode"); + if (ashmem_ != nullptr) { + return DH_SUCCESS; + } + ashmem_ = new Ashmem(fd, ashmemLength); + ashmemLength_ = ashmemLength; + lengthPerTrans_ = lengthPerTrans; + DHLOGD("Create ashmem success. fd:%{public}d, ashmem length: %{public}d, lengthPreTrans: %{public}d", + fd, ashmemLength_, lengthPerTrans_); + bool mapRet = ashmem_->MapReadAndWriteAshmem(); + if (!mapRet) { + DHLOGE("Mmap ashmem failed."); + return ERR_DH_AUDIO_NULLPTR; + } + } + return DH_SUCCESS; +} + +int32_t DMicDev::MmapStart() +{ + CHECK_NULL_RETURN(ashmem_, ERR_DH_AUDIO_NULLPTR); + std::lock_guard lock(writeAshmemMutex_); + frameIndex_ = 0; + startTime_ = 0; + isEnqueueRunning_.store(true); + enqueueDataThread_ = std::thread(&DMicDev::EnqueueThread, this); + if (pthread_setname_np(enqueueDataThread_.native_handle(), ENQUEUE_THREAD) != DH_SUCCESS) { + DHLOGE("Enqueue data thread setname failed."); + } + return DH_SUCCESS; +} + +void DMicDev::EnqueueThread() +{ + writeIndex_ = 0; + writeNum_ = 0; + DHLOGD("Enqueue thread start, lengthPerWrite length: %{public}d.", lengthPerTrans_); + FillJitterQueue(); + while (ashmem_ != nullptr && isEnqueueRunning_.load()) { + int64_t timeOffset = UpdateTimeOffset(frameIndex_, LOW_LATENCY_INTERVAL_NS, + startTime_); + DHLOGD("Write frameIndex: %{public}" PRId64", timeOffset: %{public}" PRId64, frameIndex_, timeOffset); + std::shared_ptr audioData = nullptr; + { + std::lock_guard lock(dataQueueMtx_); + if (dataQueue_.empty()) { + DHLOGD("Data queue is Empty."); + audioData = std::make_shared(param_.comParam.frameSize); + } else { + audioData = dataQueue_.front(); + dataQueue_.pop(); + } + } +#ifdef DUMP_DMICDEV_FILE + if (DaudioHidumper::GetInstance().QueryDumpDataFlag()) { + SaveFile(MIC_LOWLATENCY_FILENAME, const_cast(audioData->Data()), audioData->Size()); + } +#endif + bool writeRet = ashmem_->WriteToAshmem(audioData->Data(), audioData->Size(), writeIndex_); + if (writeRet) { + DHLOGD("Write to ashmem success! write index: %{public}d, writeLength: %{public}d.", + writeIndex_, lengthPerTrans_); + } else { + DHLOGE("Write data to ashmem failed."); + } + writeIndex_ += lengthPerTrans_; + if (writeIndex_ >= ashmemLength_) { + writeIndex_ = 0; + } + writeNum_ += static_cast(CalculateSampleNum(param_.comParam.sampleRate, timeInterval_)); + GetCurrentTime(writeTvSec_, writeTvNSec_); + frameIndex_++; + AbsoluteSleep(startTime_ + frameIndex_ * LOW_LATENCY_INTERVAL_NS - timeOffset); + } +} + +void DMicDev::FillJitterQueue() +{ + while (isEnqueueRunning_.load()) { + { + std::lock_guard lock(dataQueueMtx_); + if (dataQueue_.size() >= LOW_LATENCY_DATA_QUEUE_HALF_SIZE) { + break; + } + } + usleep(MMAP_WAIT_FRAME_US); + } + DHLOGD("Mic jitter data queue fill end."); +} + +int32_t DMicDev::MmapStop() +{ + std::lock_guard lock(writeAshmemMutex_); + isEnqueueRunning_.store(false); + if (enqueueDataThread_.joinable()) { + enqueueDataThread_.join(); + } + DHLOGI("Mic mmap stop end."); + return DH_SUCCESS; +} + +AudioParam DMicDev::GetAudioParam() const +{ + return param_; +} + +int32_t DMicDev::NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId) +{ + int32_t ret = DAudioHdiHandler::GetInstance().NotifyEvent(devId_, portId, event); + if (ret != DH_SUCCESS) { + DHLOGE("Notify event: %{public}d, result: %{public}s.", event.type, event.content.c_str()); + } + return DH_SUCCESS; +} + +int32_t DMicDev::OnStateChange(const AudioEventType type) +{ + DHLOGD("On mic device state change, type: %{public}d", type); + AudioEvent event; + switch (type) { + case AudioEventType::DATA_OPENED: + isTransReady_.store(true); + channelWaitCond_.notify_one(); + event.type = AudioEventType::MIC_OPENED; + break; + case AudioEventType::DATA_CLOSED: + isTransReady_.store(false); + event.type = AudioEventType::MIC_CLOSED; + break; + default: + break; + } + event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str()); + std::shared_ptr cbObj = audioEventCallback_.lock(); + CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); + cbObj->NotifyEvent(event); + return DH_SUCCESS; +} + +int32_t DMicDev::SendMessage(uint32_t type, std::string content, std::string dstDevId) +{ + DHLOGI("Send message to remote."); + if (type != static_cast(OPEN_MIC) && type != static_cast(CLOSE_MIC)) { + DHLOGE("Send message to remote. not OPEN_MIC or CLOSE_MIC. type: %{public}u", type); + return ERR_DH_AUDIO_NULLPTR; + } + CHECK_NULL_RETURN(micTrans_, ERR_DH_AUDIO_NULLPTR); + micTrans_->SendMessage(type, content, dstDevId); + return DH_SUCCESS; +} + +int32_t DMicDev::OnDecodeTransDataDone(const std::shared_ptr &audioData) +{ + CHECK_NULL_RETURN(audioData, ERR_DH_AUDIO_NULLPTR); + std::lock_guard lock(dataQueueMtx_); + dataQueSize_ = curStatus_ != AudioStatus::STATUS_START ? + (param_.captureOpts.capturerFlags == MMAP_MODE ? LOW_LATENCY_DATA_QUEUE_HALF_SIZE : DATA_QUEUE_HALF_SIZE) : + (param_.captureOpts.capturerFlags == MMAP_MODE ? LOW_LATENCY_DATA_QUEUE_MAX_SIZE : DATA_QUEUE_MAX_SIZE); + if (isExistedEmpty_.load()) { + dataQueSize_ = param_.captureOpts.capturerFlags == MMAP_MODE ? dataQueSize_ : DATA_QUEUE_EXT_SIZE; + } + uint64_t queueSize; + while (dataQueue_.size() > dataQueSize_) { + queueSize = static_cast(dataQueue_.size()); + DHLOGD("Data queue overflow. buf current size: %{public}" PRIu64, queueSize); + dataQueue_.pop(); + } + dataQueue_.push(audioData); + queueSize = static_cast(dataQueue_.size()); + DHLOGD("Push new mic data, buf len: %{public}" PRIu64, queueSize); + return DH_SUCCESS; +} +} // DistributedHardware +} // OHOS diff --git a/services/audiocheck/managersource/src/dspeaker_dev.cpp b/services/audiocheck/managersource/src/dspeaker_dev.cpp new file mode 100644 index 00000000..08ccfc7f --- /dev/null +++ b/services/audiocheck/managersource/src/dspeaker_dev.cpp @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2022-2023 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 "dspeaker_dev.h" + +#include +#include +#include +#include +#include +#include + +#include "daudio_constants.h" +#include "daudio_errorcode.h" +#include "daudio_hidumper.h" +#include "daudio_hisysevent.h" +#include "daudio_hitrace.h" +#include "daudio_log.h" +#include "daudio_source_manager.h" +#include "daudio_util.h" + +#undef DH_LOG_TAG +#define DH_LOG_TAG "DSpeakerDev" + +namespace OHOS { +namespace DistributedHardware { +int32_t DSpeakerDev::EnableDevice(const int32_t dhId, const std::string &capability) +{ + DHLOGI("Enable IO device, device pin: %{public}d.", dhId); + int32_t ret = DAudioHdiHandler::GetInstance().RegisterAudioDevice(devId_, dhId, capability, shared_from_this()); + if (ret != DH_SUCCESS) { + DHLOGE("Register device failed, ret: %{public}d.", ret); + DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_REGISTER_FAIL, devId_, std::to_string(dhId), ret, + "daudio register device failed."); + return ret; + } + dhId_ = dhId; + return DH_SUCCESS; +} + +int32_t DSpeakerDev::DisableDevice(const int32_t dhId) +{ + DHLOGI("Disable IO device, device pin: %{public}d.", dhId); + int32_t ret = DAudioHdiHandler::GetInstance().UnRegisterAudioDevice(devId_, dhId); + if (ret != DH_SUCCESS) { + DHLOGE("UnRegister failed, ret: %{public}d.", ret); + DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_UNREGISTER_FAIL, devId_, std::to_string(dhId), ret, + "daudio unregister device failed."); + return ret; + } + return DH_SUCCESS; +} + +int32_t DSpeakerDev::InitReceiverEngine(IAVEngineProvider *providerPtr) +{ + DHLOGI("InitReceiverEngine enter."); + return DH_SUCCESS; +} + +int32_t DSpeakerDev::InitSenderEngine(IAVEngineProvider *providerPtr) +{ + DHLOGI("InitSenderEngine enter"); + if (speakerTrans_ == nullptr) { + speakerTrans_ = std::make_shared(devId_, shared_from_this()); + } + int32_t ret = speakerTrans_->InitEngine(providerPtr); + if (ret != DH_SUCCESS) { + DHLOGE("Speaker dev initialize av sender adapter failed."); + return ret; + } + ret = speakerTrans_->CreateCtrl(); + if (ret != DH_SUCCESS) { + DHLOGE("Create ctrl channel failed."); + } + return ret; +} + +void DSpeakerDev::OnEngineTransEvent(const AVTransEvent &event) +{ + if (event.type == EventType::EVENT_START_SUCCESS) { + OnStateChange(DATA_OPENED); + } else if ((event.type == EventType::EVENT_STOP_SUCCESS) || + (event.type == EventType::EVENT_CHANNEL_CLOSED) || + (event.type == EventType::EVENT_START_FAIL)) { + OnStateChange(DATA_CLOSED); + } +} + +void DSpeakerDev::OnEngineTransMessage(const std::shared_ptr &message) +{ + CHECK_NULL_VOID(message); + DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str()); + DAudioSourceManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_, + message->type_, message->content_); +} + +int32_t DSpeakerDev::OpenDevice(const std::string &devId, const int32_t dhId) +{ + DHLOGI("Open speaker device devId: %{public}s, dhId: %{public}d.", GetAnonyString(devId).c_str(), dhId); + std::shared_ptr cbObj = audioEventCallback_.lock(); + CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); + + cJSON *jParam = cJSON_CreateObject(); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId).c_str()); + char *jsonData = cJSON_PrintUnformatted(jParam); + if (jsonData == nullptr) { + DHLOGE("Failed to create JSON data."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NULLPTR; + } + std::string jsonDataStr(jsonData); + AudioEvent event(AudioEventType::OPEN_SPEAKER, jsonDataStr); + cbObj->NotifyEvent(event); + DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_OPEN, devId, std::to_string(dhId), + "daudio spk device open success."); + cJSON_Delete(jParam); + cJSON_free(jsonData); + return DH_SUCCESS; +} + +int32_t DSpeakerDev::CloseDevice(const std::string &devId, const int32_t dhId) +{ + DHLOGI("Close speaker device devId: %{public}s, dhId: %{public}d.", GetAnonyString(devId).c_str(), dhId); + std::shared_ptr cbObj = audioEventCallback_.lock(); + CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); + + cJSON *jParam = cJSON_CreateObject(); + CHECK_NULL_RETURN(jParam, ERR_DH_AUDIO_NULLPTR); + cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId).c_str()); + char *jsonData = cJSON_PrintUnformatted(jParam); + if (jsonData == nullptr) { + DHLOGE("Failed to create JSON data."); + cJSON_Delete(jParam); + return ERR_DH_AUDIO_NULLPTR; + } + std::string jsonDataStr(jsonData); + AudioEvent event(AudioEventType::CLOSE_SPEAKER, jsonDataStr); + cbObj->NotifyEvent(event); + DAudioHisysevent::GetInstance().SysEventWriteBehavior(DAUDIO_CLOSE, devId, std::to_string(dhId), + "daudio spk device close success."); + curPort_ = 0; + cJSON_Delete(jParam); + cJSON_free(jsonData); + return DH_SUCCESS; +} + +int32_t DSpeakerDev::SetParameters(const std::string &devId, const int32_t dhId, const AudioParamHDF ¶m) +{ + DHLOGD("Set speaker parameters {samplerate: %{public}d, channelmask: %{public}d, format: %{public}d, " + "streamusage: %{public}d, period: %{public}d, framesize: %{public}d, renderFlags: %{public}d, " + "ext{%{public}s}}.", param.sampleRate, param.channelMask, param.bitFormat, param.streamUsage, + param.period, param.frameSize, param.renderFlags, param.ext.c_str()); + curPort_ = dhId; + paramHDF_ = param; + + param_.comParam.sampleRate = paramHDF_.sampleRate; + param_.comParam.channelMask = paramHDF_.channelMask; + param_.comParam.bitFormat = paramHDF_.bitFormat; + param_.comParam.codecType = AudioCodecType::AUDIO_CODEC_AAC; + param_.comParam.frameSize = paramHDF_.frameSize; + param_.renderOpts.contentType = CONTENT_TYPE_MUSIC; + param_.renderOpts.renderFlags = paramHDF_.renderFlags; + param_.renderOpts.streamUsage = paramHDF_.streamUsage; + return DH_SUCCESS; +} + +int32_t DSpeakerDev::NotifyEvent(const std::string &devId, int32_t dhId, const AudioEvent &event) +{ + DHLOGD("Notify speaker event."); + std::shared_ptr cbObj = audioEventCallback_.lock(); + CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); + AudioEvent audioEvent(event.type, event.content); + cbObj->NotifyEvent(audioEvent); + return DH_SUCCESS; +} + +int32_t DSpeakerDev::SetUp() +{ + DHLOGI("Set up speaker device."); + CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR); + + int32_t ret = speakerTrans_->SetUp(param_, param_, shared_from_this(), CAP_SPK); + if (ret != DH_SUCCESS) { + DHLOGE("Speaker trans set up failed. ret:%{public}d", ret); + return ret; + } + return DH_SUCCESS; +} + +int32_t DSpeakerDev::Start() +{ + DHLOGI("Start speaker device."); + CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR); + int32_t ret = speakerTrans_->Start(); + if (ret != DH_SUCCESS) { + DHLOGE("Speaker trans start failed, ret: %{public}d.", ret); + return ret; + } + std::unique_lock lck(channelWaitMutex_); + auto status = channelWaitCond_.wait_for(lck, std::chrono::seconds(CHANNEL_WAIT_SECONDS), + [this]() { return isTransReady_.load(); }); + if (!status) { + DHLOGE("Wait channel open timeout(%{public}ds).", CHANNEL_WAIT_SECONDS); + return ERR_DH_AUDIO_SA_WAIT_TIMEOUT; + } + isOpened_.store(true); + return DH_SUCCESS; +} + +int32_t DSpeakerDev::Stop() +{ + DHLOGI("Stop speaker device."); + CHECK_NULL_RETURN(speakerTrans_, DH_SUCCESS); + isOpened_.store(false); + isTransReady_.store(false); + int32_t ret = speakerTrans_->Stop(); + if (ret != DH_SUCCESS) { + DHLOGE("Stop speaker trans failed, ret: %{public}d.", ret); + return ret; + } + return DH_SUCCESS; +} + +int32_t DSpeakerDev::Release() +{ + DHLOGI("Release speaker device."); + if (ashmem_ != nullptr) { + ashmem_->UnmapAshmem(); + ashmem_->CloseAshmem(); + ashmem_ = nullptr; + DHLOGI("UnInit ashmem success."); + } + CHECK_NULL_RETURN(speakerTrans_, DH_SUCCESS); + int32_t ret = speakerTrans_->Release(); + if (ret != DH_SUCCESS) { + DHLOGE("Release speaker trans failed, ret: %{public}d.", ret); + } + dumpFlag_.store(false); + return DH_SUCCESS; +} + +int32_t DSpeakerDev::Pause() +{ + DHLOGI("Pause."); + CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR); + int32_t ret = speakerTrans_->Pause(); + if (ret != DH_SUCCESS) { + DHLOGE("Pause speaker trans failed, ret: %{public}d.", ret); + return ret; + } + DHLOGI("Pause success."); + return DH_SUCCESS; +} + +int32_t DSpeakerDev::Restart() +{ + DHLOGI("Restart."); + CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR); + int32_t ret = speakerTrans_->Restart(param_, param_); + if (ret != DH_SUCCESS) { + DHLOGE("Restart speaker trans failed, ret: %{public}d.", ret); + return ret; + } + DHLOGI("Restart success."); + return DH_SUCCESS; +} + +bool DSpeakerDev::IsOpened() +{ + return isOpened_.load(); +} + +int32_t DSpeakerDev::ReadStreamData(const std::string &devId, const int32_t dhId, std::shared_ptr &data) +{ + (void)devId; + (void)dhId; + (void)data; + DHLOGI("Dspeaker dev not support read stream data."); + return DH_SUCCESS; +} + +int32_t DSpeakerDev::WriteStreamData(const std::string &devId, const int32_t dhId, std::shared_ptr &data) +{ + DHLOGD("Write stream data, dhId:%{public}d", dhId); + int64_t startTime = GetNowTimeUs(); + CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR); +#ifdef DUMP_DSPEAKERDEV_FILE + if (DaudioHidumper::GetInstance().QueryDumpDataFlag()) { + if (!dumpFlag_) { + AudioEvent event(NOTIFY_HDF_SPK_DUMP, ""); + NotifyHdfAudioEvent(event, dhId); + dumpFlag_.store(true); + } + SaveFile(SPK_DEV_FILENAME, const_cast(data->Data()), data->Size()); + } +#endif + int32_t ret = speakerTrans_->FeedAudioData(data); + if (ret != DH_SUCCESS) { + DHLOGE("Write stream data failed, ret: %{public}d.", ret); + return ret; + } + int64_t endTime = GetNowTimeUs(); + if (IsOutDurationRange(startTime, endTime, lastwriteStartTime_)) { + DHLOGE("This time write data spend: %{public}" PRId64" us, The interval of write data this time and " + "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastwriteStartTime_); + } + lastwriteStartTime_ = startTime; + return DH_SUCCESS; +} + +int32_t DSpeakerDev::ReadMmapPosition(const std::string &devId, const int32_t dhId, + uint64_t &frames, CurrentTimeHDF &time) +{ + DHLOGD("Read mmap position. frames: %{public}" PRIu64", tvsec: %{public}" PRId64", tvNSec:%{public}" PRId64, + readNum_, readTvSec_, readTvNSec_); + frames = readNum_; + time.tvSec = readTvSec_; + time.tvNSec = readTvNSec_; + return DH_SUCCESS; +} + +int32_t DSpeakerDev::RefreshAshmemInfo(const std::string &devId, const int32_t dhId, + int32_t fd, int32_t ashmemLength, int32_t lengthPerTrans) +{ + DHLOGD("RefreshAshmemInfo: fd:%{public}d, ashmemLength: %{public}d, lengthPerTrans: %{public}d", + fd, ashmemLength, lengthPerTrans); + if (param_.renderOpts.renderFlags == MMAP_MODE) { + DHLOGI("DSpeaker dev low-latency mode"); + if (ashmem_ != nullptr) { + return DH_SUCCESS; + } + ashmem_ = new Ashmem(fd, ashmemLength); + ashmemLength_ = ashmemLength; + lengthPerTrans_ = lengthPerTrans; + DHLOGI("Create ashmem success. fd:%{public}d, ashmem length: %{public}d, lengthPreTrans: %{public}d", + fd, ashmemLength_, lengthPerTrans_); + bool mapRet = ashmem_->MapReadAndWriteAshmem(); + if (!mapRet) { + DHLOGE("Mmap ashmem failed."); + return ERR_DH_AUDIO_NULLPTR; + } + } + return DH_SUCCESS; +} + +int32_t DSpeakerDev::MmapStart() +{ + CHECK_NULL_RETURN(ashmem_, ERR_DH_AUDIO_NULLPTR); + isEnqueueRunning_.store(true); + enqueueDataThread_ = std::thread(&DSpeakerDev::EnqueueThread, this); + if (pthread_setname_np(enqueueDataThread_.native_handle(), ENQUEUE_THREAD) != DH_SUCCESS) { + DHLOGE("Enqueue data thread setname failed."); + } + return DH_SUCCESS; +} + +void DSpeakerDev::EnqueueThread() +{ + readIndex_ = 0; + readNum_ = 0; + frameIndex_ = 0; + DHLOGI("Enqueue thread start, lengthPerRead length: %{public}d.", lengthPerTrans_); + while (ashmem_ != nullptr && isEnqueueRunning_.load()) { + int64_t timeOffset = UpdateTimeOffset(frameIndex_, LOW_LATENCY_INTERVAL_NS, + startTime_); + DHLOGD("Read frameIndex: %{public}" PRId64", timeOffset: %{public}" PRId64, frameIndex_, timeOffset); + auto readData = ashmem_->ReadFromAshmem(lengthPerTrans_, readIndex_); + DHLOGI("Read from ashmem success! read index: %{public}d, readLength: %{public}d.", + readIndex_, lengthPerTrans_); + std::shared_ptr audioData = std::make_shared(lengthPerTrans_); + if (readData != nullptr) { + const uint8_t *readAudioData = reinterpret_cast(readData); + if (memcpy_s(audioData->Data(), audioData->Capacity(), readAudioData, param_.comParam.frameSize) != EOK) { + DHLOGE("Copy audio data failed."); + } + } + CHECK_NULL_VOID(speakerTrans_); +#ifdef DUMP_DSPEAKERDEV_FILE + if (DaudioHidumper::GetInstance().QueryDumpDataFlag()) { + SaveFile(SPK_LOWLATENCY_FILENAME, const_cast(audioData->Data()), audioData->Size()); + } +#endif + int32_t ret = speakerTrans_->FeedAudioData(audioData); + if (ret != DH_SUCCESS) { + DHLOGE("Speaker enqueue thread, write stream data failed, ret: %{public}d.", ret); + } + readIndex_ += lengthPerTrans_; + if (readIndex_ >= ashmemLength_) { + readIndex_ = 0; + } + readNum_ += static_cast(CalculateSampleNum(param_.comParam.sampleRate, timeInterval_)); + GetCurrentTime(readTvSec_, readTvNSec_); + frameIndex_++; + AbsoluteSleep(startTime_ + frameIndex_ * LOW_LATENCY_INTERVAL_NS - timeOffset); + } +} + +int32_t DSpeakerDev::MmapStop() +{ + isEnqueueRunning_.store(false); + if (enqueueDataThread_.joinable()) { + enqueueDataThread_.join(); + } + DHLOGI("Spk mmap stop end."); + return DH_SUCCESS; +} + +AudioParam DSpeakerDev::GetAudioParam() const +{ + return param_; +} + +int32_t DSpeakerDev::SendMessage(uint32_t type, std::string content, std::string dstDevId) +{ + DHLOGI("Send message to remote."); + if (type != static_cast(OPEN_SPEAKER) && type != static_cast(CLOSE_SPEAKER) && + type != static_cast(CHANGE_PLAY_STATUS) && type != static_cast(VOLUME_SET) && + type != static_cast(VOLUME_MUTE_SET)) { + DHLOGE("Send message to remote. not OPEN_SPK or CLOSE_SPK. type: %{public}u", type); + return ERR_DH_AUDIO_NULLPTR; + } + CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR); + speakerTrans_->SendMessage(type, content, dstDevId); + return DH_SUCCESS; +} + +int32_t DSpeakerDev::NotifyHdfAudioEvent(const AudioEvent &event, const int32_t portId) +{ + int32_t ret = DAudioHdiHandler::GetInstance().NotifyEvent(devId_, portId, event); + if (ret != DH_SUCCESS) { + DHLOGE("Notify event: %{public}d, result: %{public}s.", event.type, event.content.c_str()); + } + return DH_SUCCESS; +} + +int32_t DSpeakerDev::OnStateChange(const AudioEventType type) +{ + DHLOGI("On speaker device state change, type: %{public}d.", type); + AudioEvent event; + switch (type) { + case AudioEventType::DATA_OPENED: + isTransReady_.store(true); + channelWaitCond_.notify_all(); + event.type = AudioEventType::SPEAKER_OPENED; + break; + case AudioEventType::DATA_CLOSED: + isOpened_.store(false); + isTransReady_.store(false); + event.type = AudioEventType::SPEAKER_CLOSED; + break; + default: + break; + } + event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str()); + std::shared_ptr cbObj = audioEventCallback_.lock(); + CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR); + cbObj->NotifyEvent(event); + return DH_SUCCESS; +} + +int32_t DSpeakerDev::OnDecodeTransDataDone(const std::shared_ptr &audioData) +{ + (void) audioData; + return DH_SUCCESS; +} +} // DistributedHardware +} // OHOS -- Gitee