diff --git a/hdf_service/distributed_audio/distributedaudiotest/BUILD.gn b/hdf_service/distributed_audio/distributedaudiotest/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..83292ae3515192a0ef9aa97c671e1fffa37fd968 --- /dev/null +++ b/hdf_service/distributed_audio/distributedaudiotest/BUILD.gn @@ -0,0 +1,58 @@ +# 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. + +import("//build/config/features.gni") +import("//build/ohos.gni") +import("//build/test.gni") +import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni") +import("//drivers/peripheral/adapter/base/hidl_adapter.gni") +import("//test/xts/tools/build/suite.gni") +import("../../../distributedaudio.gni") + +module_output_path = "distributedhardware/dctsdisaudiotest" + +ohos_moduletest_suite("DctsdisAudioTest") { + module_out_path = module_output_path + include_dirs = [ + "./include", + "${driver_audio_path}/include", + "${services_path}/hdfaudioclient/include", + "${hdf_service_path}/hdi_service/common/include", + ] + + sources = [ + "daudio_automat_test.cpp", + "distributed_audio_test.cpp", + ] + + deps = [ + "$hdf_uhdf_path/utils:libhdf_utils", + "${services_path}/hdfaudioclient:daudio_client", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + + defines = [ + "HI_LOG_ENABLE", + "DH_LOG_TAG=\"DctsdisAudioTest\"", + "LOG_DOMAIN=0xD004100", + ] + + install_enable = true + install_images = [ chipset_base_dir ] + subsystem_name = "distributedhardware" + part_name = "distributed_audio" +} diff --git a/hdf_service/distributed_audio/distributedaudiotest/Test.json b/hdf_service/distributed_audio/distributedaudiotest/Test.json new file mode 100644 index 0000000000000000000000000000000000000000..01f2723bc64d375ca919a27becd818bcd650376d --- /dev/null +++ b/hdf_service/distributed_audio/distributedaudiotest/Test.json @@ -0,0 +1,22 @@ +{ + "description": "Config for disAudio test cases", + "driver": { + "module-name": "DctsdisAudioTest", + "native-test-timeout": "120000", + "native-test-device-path": "/data/local/tmp", + "runtime-hint": "1s", + "type": "CppTest" + }, + "kits": [ + { + "post-push" : [ + "chmod -R 777 /data/local/tmp/*" + ], + "push": [ + "DctsdisAudioTest->/data/local/tmp/DctsdisAudioTest" + ], + "type": "PushKit" + } + ] +} + diff --git a/hdf_service/distributed_audio/distributedaudiotest/daudio_automat_test.cpp b/hdf_service/distributed_audio/distributedaudiotest/daudio_automat_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d5c79559b114a140e0ec175dda1e803f7d6d323 --- /dev/null +++ b/hdf_service/distributed_audio/distributedaudiotest/daudio_automat_test.cpp @@ -0,0 +1,275 @@ +/* + * 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 +#include "distributed_audio_test.h" + +#include +#include +#include + +using namespace testing::ext; +using namespace OHOS::DistributedHardware; + +constexpr int32_t DAUDIO_OK = 0; +constexpr int32_t DAUDIO_DALAY_TIME1 = 3; +constexpr int32_t DAUDIO_DALAY_TIME2 = 10; +constexpr int32_t RUN_TIMES = 20; +constexpr int32_t MAX_VOLUME = 15; + +class DAudioAutomatTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + DAudioAutomatTest(); +}; + +void DAudioAutomatTest::SetUpTestCase(void) +{ + if (InitTestDemo() != DAUDIO_OK) { + std::cout <<"demo test:InitTestDemo error" << std::endl; + return; + } + + if (FindAudioDevice() != DAUDIO_OK) { + return; + } +} +void DAudioAutomatTest::TearDownTestCase(void) {} +void DAudioAutomatTest::SetUp(void) {} +void DAudioAutomatTest::TearDown(void) {} +DAudioAutomatTest::DAudioAutomatTest(void) {} + +/** + * @tc.number : DAudioTest_001 + * @tc.name : find audio device test + * @tc.desc : find audio device + */ +HWTEST_F(DAudioAutomatTest, DAudioTest_001, TestSize.Level1) +{ + std::cout << "start run DAudioTest_001." << std::endl; + EXPECT_EQ(DAUDIO_OK, FindAudioDevice()); +} + +/** + * @tc.number : DAudioTest_002 + * @tc.name : open、close speaker test + * @tc.desc : open、close speaker + */ +HWTEST_F(DAudioAutomatTest, DAudioTest_002, TestSize.Level1) +{ + std::cout << "start run DAudioTest_002." << std::endl; + std::string retStr = "false"; + retStr = OpenSpk(); + EXPECT_EQ("true", retStr); + retStr = CloseSpk(); + EXPECT_EQ("true", retStr); +} + +/** + * @tc.number : DAudioTest_003 + * @tc.name : open、close speaker test + * @tc.desc : open、close speaker 20 times + */ +HWTEST_F(DAudioAutomatTest, DAudioTest_003, TestSize.Level1) +{ + std::cout << "start run DAudioTest_003." << std::endl; + for (int32_t i = 0; i < RUN_TIMES; ++i) { + std::string retStr = "false"; + retStr = OpenSpk(); + EXPECT_EQ("true", retStr); + retStr = CloseSpk(); + EXPECT_EQ("true", retStr); + } +} + +/** + * @tc.number : DAudioTest_004 + * @tc.name : open、close mic test + * @tc.desc : open、close mic + */ +HWTEST_F(DAudioAutomatTest, DAudioTest_004, TestSize.Level1) +{ + std::cout << "start run DAudioTest_004." << std::endl; + std::string retStr = "false"; + retStr = OpenMic(); + EXPECT_EQ("true", retStr); + retStr = CloseMic(); + EXPECT_EQ("true", retStr); +} + +/** + * @tc.number : DAudioTest_005 + * @tc.name : open、close mic test + * @tc.desc : open、close mic 20 times + */ +HWTEST_F(DAudioAutomatTest, DAudioTest_005, TestSize.Level1) +{ + std::cout << "start run DAudioTest_005." << std::endl; + for (int32_t i = 0; i < RUN_TIMES; ++i) { + std::string retStr = "false"; + retStr = OpenMic(); + EXPECT_EQ("true", retStr); + retStr = CloseMic(); + EXPECT_EQ("true", retStr); + } +} + +/** + * @tc.number : DAudioTest_006 + * @tc.name : start、stop render test + * @tc.desc : start、stop render + */ +HWTEST_F(DAudioAutomatTest, DAudioTest_006, TestSize.Level1) +{ + std::cout << "start run DAudioTest_006." << std::endl; + std::string retStr = "false"; + retStr = OpenSpk(); + EXPECT_EQ("true", retStr); + retStr = StartRender(); + EXPECT_EQ("true", retStr); + sleep(DAUDIO_DALAY_TIME2); + retStr = StopRender(); + EXPECT_EQ("true", retStr); + retStr = CloseSpk(); + EXPECT_EQ("true", retStr); +} + +/** + * @tc.number : DAudioTest_007 + * @tc.name : start、stop Capture test + * @tc.desc : start、stop Capture + */ +HWTEST_F(DAudioAutomatTest, DAudioTest_007, TestSize.Level1) +{ + std::cout << "start run DAudioTest_007." << std::endl; + std::string retStr = "false"; + retStr = OpenMic(); + EXPECT_EQ("true", retStr); + retStr = StartCapture(); + EXPECT_EQ("true", retStr); + sleep(DAUDIO_DALAY_TIME2); + retStr = StopCapture(); + EXPECT_EQ("true", retStr); + retStr = CloseMic(); + EXPECT_EQ("true", retStr); +} + +/** + * @tc.number : DAudioTest_008 + * @tc.name : setvolume、getvolume test + * @tc.desc : setvolume、getvolume render 20 times + */ +HWTEST_F(DAudioAutomatTest, DAudioTest_008, TestSize.Level1) +{ + std::cout << "start run DAudioTest_008." << std::endl; + std::string retStr = "false"; + retStr = OpenSpk(); + EXPECT_EQ("true", retStr); + retStr = StartRender(); + EXPECT_EQ("true", retStr); + std::srand((unsigned int)time(nullptr)); + for (int i = 0; i < RUN_TIMES; ++i) { + int volume = rand() % (MAX_VOLUME + 1); + retStr = std::to_string(volume); + retStr = SetVolume(retStr); + EXPECT_EQ("true", retStr); + sleep(DAUDIO_DALAY_TIME2); + retStr = GetVolume(); + EXPECT_EQ("true", retStr); + } + retStr = StopRender(); + EXPECT_EQ("true", retStr); + retStr = CloseSpk(); + EXPECT_EQ("true", retStr); +} + +/** + * @tc.number : DAudioTest_009 + * @tc.name : startcapture、stopcapture test + * @tc.desc : startcapture、stopcapture render + */ +HWTEST_F(DAudioAutomatTest, DAudioTest_009, TestSize.Level1) +{ + std::cout << "start run DAudioTest_009." << std::endl; + std::string retStr = "false"; + retStr = OpenSpk(); + EXPECT_EQ("true", retStr); + sleep(DAUDIO_DALAY_TIME1); + retStr = OpenMic(); + EXPECT_EQ("true", retStr); + sleep(DAUDIO_DALAY_TIME1); + retStr = StartRender(); + EXPECT_EQ("true", retStr); + retStr = StartCapture(); + EXPECT_EQ("true", retStr); + sleep(DAUDIO_DALAY_TIME2); + retStr = StopCapture(); + EXPECT_EQ("true", retStr); + retStr = StopRender(); + EXPECT_EQ("true", retStr); + retStr = CloseSpk(); + EXPECT_EQ("true", retStr); + sleep(DAUDIO_DALAY_TIME1); + retStr = CloseMic(); + EXPECT_EQ("true", retStr); + sleep(DAUDIO_DALAY_TIME1); +} + +/** + * @tc.number : DAudioTest_010 + * @tc.name : start、stop render test + * @tc.desc : start、stop render 20 times + */ +HWTEST_F(DAudioAutomatTest, DAudioTest_010, TestSize.Level1) +{ + std::cout << "start run DAudioTest_010." << std::endl; + std::string retStr = "false"; + retStr = OpenSpk(); + for (int32_t i = 0; i < RUN_TIMES; ++i) { + retStr = StartRender(); + EXPECT_EQ("true", retStr); + sleep(DAUDIO_DALAY_TIME2); + retStr = StopRender(); + EXPECT_EQ("true", retStr); + sleep(DAUDIO_DALAY_TIME1); + } + retStr = CloseSpk(); + EXPECT_EQ("true", retStr); +} + +/** + * @tc.number : DAudioTest_011 + * @tc.name : start、stop Capture test + * @tc.desc : start、stop Capture + */ +HWTEST_F(DAudioAutomatTest, DAudioTest_011, TestSize.Level1) +{ + std::cout << "start run DAudioTest_011." << std::endl; + std::string retStr = "false"; + retStr = OpenMic(); + for (int32_t i = 0; i < RUN_TIMES; ++i) { + retStr = StartCapture(); + EXPECT_EQ("true", retStr); + sleep(DAUDIO_DALAY_TIME2); + retStr = StopCapture(); + EXPECT_EQ("true", retStr); + sleep(DAUDIO_DALAY_TIME1); + } + retStr = CloseMic(); + EXPECT_EQ("true", retStr); +} \ No newline at end of file diff --git a/hdf_service/distributed_audio/distributedaudiotest/distributed_audio_test.cpp b/hdf_service/distributed_audio/distributedaudiotest/distributed_audio_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f8b449da5cc532407f42d7d8987c6275f3ec5910 --- /dev/null +++ b/hdf_service/distributed_audio/distributedaudiotest/distributed_audio_test.cpp @@ -0,0 +1,565 @@ + +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include "unistd.h" +#include "distributed_audio_test.h" + +static const std::string SERVER_FIFO = "/data/seqnum_sv"; +static const std::string CLIENT_FIFO_TEMPLATE = "/data/seqnum_cl.%ld"; +using namespace OHOS::DistributedHardware; + +struct Request { + pid_t pid; + int commandNum; + char reqString[70]; + int seqLen; +}; + +struct Response { + int seqNum; + char resString[CMD_EXECUTING_RETURN_LENGHT_MAX]; +}; + +static AudioManager *g_manager = nullptr; +static AudioAdapter *g_adapter = nullptr; +static AudioRender *g_render = nullptr; +static AudioCapture *g_capture = nullptr; +static AudioAdapterDescriptor *g_devices = nullptr; + +static constexpr const char* PLAY_THREAD = "playThread"; +static constexpr const char* CAPTURE_THREAD = "captureThread"; + +const char *adaptName = nullptr; +int32_t g_deviceNum = 0; +int32_t g_frameNum = 0; +int32_t g_frameIndex = 0; +int32_t g_micFrameNum = 0; +bool g_isInitRenderData = false; +static std::vector renderData; + +static DeviceStatus g_spkStatus = DEVICE_IDLE; +static DeviceStatus g_micStatus = DEVICE_IDLE; + +static std::thread g_palyingThread; +static std::thread g_capingThread; +FILE *g_micFile = nullptr; + +static int64_t GetNowTimeUs() +{ + std::chrono::microseconds nowUs = + std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()); + return nowUs.count(); +} + +int32_t InitTestDemo() +{ + std::cout << "**********************************************************************************" << std::endl; + std::cout << "Distributed Audio Test Demo Bin v1.3." << std::endl; + std::cout << "**********************************************************************************" << std::endl; + std::cout << std::endl; + std::cout << "Init distributed audio hdf service." << std::endl; + g_manager = GetAudioManagerFuncs(); + if (g_manager == nullptr) { + std::cout << "Distributed audio manager is null, quit!" << std::endl; + return ERR_DH_AUDIO_HDF_FAIL; + } + std::cout << "Load audio manager success." << std::endl; + return DH_SUCCESS; +} + +int32_t FindAudioDevice() +{ + if (g_manager == nullptr) { + return ERR_DH_AUDIO_HDF_NULLPTR; + } + int32_t ret = g_manager->GetAllAdapters(g_manager, &g_devices, &g_deviceNum); + if (ret != DH_SUCCESS) { + std::cout << "Get audio devices failed!"; + return ERR_DH_AUDIO_HDF_NULLPTR; + } + std::string res = "true;"; + std::cout << "Get audio devices success, adapter size: " << g_deviceNum << std::endl; + for (int32_t index = 0; index < g_deviceNum; index++) { + const AudioAdapterDescriptor &desc = g_devices[index]; + std::cout << "Device[" << index << "] ID: " << desc.adapterName << std::endl; + adaptName = desc.adapterName; + std::cout << "pin list: "; + for (uint32_t i = 0; i < desc.portNum; i++) { + std::cout << desc.ports[i].portId << ", "; + } + std::cout << std::endl; + } + return DH_SUCCESS; +} + +static void HandleDevError(const char *condition, const char *value) +{ + if (condition[TYPE_OFFSET] == DEV_TYPE_SPK && g_spkStatus != DEVICE_IDLE) { + CloseSpk(); + } + + if (condition[TYPE_OFFSET] == DEV_TYPE_MIC && g_micStatus == DEVICE_IDLE) { + CloseMic(); + } + + std::cout << "Receive abnormal event, Demo quit." << std::endl; +} + +static int32_t ParamEventCallback(AudioExtParamKey key, const char *condition, const char *value, void *reserved, + void *cookie) +{ + std::string val(value); + std::string con(condition); + std::cout << std::endl; + std::cout << "**********************************************************************************" << std::endl; + std::cout << "Event recived: " << key << std::endl; + std::cout << "Condition: " << con << std::endl; + std::cout << "Value: " << val << std::endl; + std::cout << "**********************************************************************************" << std::endl; + std::cout << std::endl; + + if (key == AudioExtParamKey::AUDIO_EXT_PARAM_KEY_STATUS && con.rfind("ERR_EVENT", 0) == 0) { + HandleDevError(condition, value); + } + return DH_SUCCESS; +} + +static int32_t LoadSpkDev() +{ + std::cout << "Open SPK device , device Id:" << adaptName << std::endl; + + struct AudioAdapterDescriptor *dev = nullptr; + for (int32_t index = 0; index < g_deviceNum; index++) { + struct AudioAdapterDescriptor &desc = g_devices[index]; + if (strcmp(desc.adapterName, adaptName) == 0) { + dev = &desc; + break; + } + } + if (dev == nullptr) { + std::cout << "Input device id is wrong." << std::endl; + FindAudioDevice(); + return ERR_DH_AUDIO_HDF_FAIL; + } + if (g_manager == nullptr) { + return ERR_DH_AUDIO_HDF_FAIL; + } + if (g_adapter == nullptr) { + int32_t ret = g_manager->LoadAdapter(g_manager, dev, &g_adapter); + if (ret != DH_SUCCESS || g_adapter == nullptr) { + std::cout << "Load audio device failed, ret: " << ret << std::endl; + return ERR_DH_AUDIO_HDF_FAIL; + } + } + std::cout << "Load audio device success." << std::endl; + return DH_SUCCESS; +} + +std::string OpenSpk() +{ + if (g_spkStatus != DEVICE_IDLE) { + std::cout << "Speaker device is already opened." << std::endl; + return "true"; + } + if (LoadSpkDev() != DH_SUCCESS) { + return "false"; + } + ParamCallback callback = ParamEventCallback; + int32_t ret = g_adapter->RegExtraParamObserver(g_adapter, callback, nullptr); + if (ret != DH_SUCCESS) { + std::cout << "Register observer failed, ret: " << ret << std::endl; + return "false"; + } + + struct AudioDeviceDescriptor renderDesc; + renderDesc.pins = AudioPortPin::PIN_OUT_SPEAKER; + renderDesc.desc = nullptr; + AudioSampleAttributes g_rattrs = {}; + g_rattrs.type = AUDIO_IN_MEDIA; + g_rattrs.interleaved = RENDER_INTER_LEAVED; + g_rattrs.streamId = RENDER_STREAM_ID; + g_rattrs.channelCount = RENDER_CHANNEL_MASK; + g_rattrs.sampleRate = AUDIO_SAMPLE_RATE; + g_rattrs.format = AudioFormat::AUDIO_FORMAT_TYPE_PCM_16_BIT; + ret = g_adapter->CreateRender(g_adapter, &renderDesc, &g_rattrs, &g_render); + if (ret != DH_SUCCESS || g_render == nullptr) { + std::cout << "Open SPK device failed, ret: " << ret << std::endl; + return "false"; + } + g_spkStatus = DEVICE_OPEN; + std::cout << "Open SPK device success." << std::endl; + return "true"; +} + +static void WriteStreamWait(const int64_t &startTime) +{ + int64_t endTime = GetNowTimeUs(); + int64_t passTime = endTime - startTime; + + if (passTime > AUDIO_FRAME_TIME_INTERFAL_DEFAULT) { + return; + } + int64_t remainTime = AUDIO_FRAME_TIME_INTERFAL_DEFAULT - passTime; + std::this_thread::sleep_for(std::chrono::microseconds(remainTime)); +} + +static void Play() +{ + if (g_render == nullptr) { + std::cout << "SPK device is null." << std::endl; + return; + } + if (pthread_setname_np(pthread_self(), PLAY_THREAD) != DH_SUCCESS) { + std::cout << "Play thread setname failed." << std::endl; + } + std::cout << "Playing thread started." << std::endl; + g_render->control.Start((AudioHandle)g_render); + g_spkStatus = DEVICE_START; + + uint64_t size = 0; + while (g_spkStatus == DEVICE_START) { + int64_t startTime = GetNowTimeUs(); + int32_t ret = g_render->RenderFrame(g_render, renderData[g_frameIndex], RENDER_FRAME_SIZE, &size); + if (ret != DH_SUCCESS) { + std::cout<<"RenderFrame failed, index: "<< g_frameIndex << ", ret: " << ret << std::endl; + } + g_frameIndex++; + if (g_frameNum != 0 && g_frameIndex == g_frameNum) { + g_frameIndex = 0; + } + WriteStreamWait(startTime); + } + std::cout << "Playing thread stopped." << std::endl; +} + +std::string StartRender() +{ + if (g_spkStatus == DEVICE_IDLE) { + return "Speaker device is not opened, start render failed."; + } + + if (g_spkStatus == DEVICE_OPEN) { + WavHdr wavHeader; + size_t headerSize = sizeof(WavHdr); + if (!g_isInitRenderData) { + struct stat statbuf; + stat(SPK_FILE_PATH, &statbuf); + int32_t size = statbuf.st_size; + g_frameNum = (size - headerSize) / RENDER_FRAME_SIZE; + std::cout << "Audio file frame num: " << g_frameNum << std::endl; + for (int32_t j = 0; j < g_frameNum; j++) { + uint8_t *frame = new uint8_t[RENDER_FRAME_SIZE](); + renderData.push_back(frame); + } + g_isInitRenderData = true; + } + FILE *wavFile = fopen(SPK_FILE_PATH, "rb"); + fread(&wavHeader, 1, headerSize, wavFile); + for (int32_t i = 0; i < g_frameNum; i++) { + fread(renderData[i], 1, RENDER_FRAME_SIZE, wavFile); + } + fclose(wavFile); + g_frameIndex = 0; + g_palyingThread = std::thread(Play); + return "true"; + } + if (g_spkStatus == DEVICE_START) { + return "Speaker device is started."; + } + if (g_spkStatus == DEVICE_STOP) { + g_palyingThread = std::thread(Play); + } + return "true"; +} + +std::string StopRender() +{ + if (g_render == nullptr) { + return "SPK device is null."; + } + + if (g_spkStatus == DEVICE_IDLE) { + return "Speaker device is not opened."; + } + + if (g_spkStatus == DEVICE_OPEN) { + return "Speaker device is not started."; + } + + if (g_spkStatus == DEVICE_STOP) { + return "Speaker device is already stoped."; + } + + g_spkStatus = DEVICE_STOP; + if (g_palyingThread.joinable()) { + g_palyingThread.join(); + } + g_render->control.Stop((AudioHandle)g_render); + return "true"; +} + +std::string CloseSpk() +{ + if (g_spkStatus == DEVICE_IDLE) { + return "Speaker device is not opened."; + } + + if (g_spkStatus == DEVICE_START) { + StopRender(); + } + + int32_t ret = g_adapter->DestroyRender(g_adapter, g_render); + if (ret != DH_SUCCESS) { + return "Close speaker failed"; + } + if (g_micStatus == DEVICE_IDLE) { + g_manager->UnloadAdapter(g_manager, g_adapter); + g_adapter = nullptr; + } + g_spkStatus = DEVICE_IDLE; + + if (g_isInitRenderData) { + for (auto &p : renderData) { + delete[] p; + } + renderData.clear(); + g_isInitRenderData = false; + } + return "true"; +} + +static int32_t LoadMicDev() +{ + std::cout << "Open MIC device ,input device Id:" << adaptName << std::endl; + + struct AudioAdapterDescriptor *dev = nullptr; + for (int32_t index = 0; index < g_deviceNum; index++) { + struct AudioAdapterDescriptor &desc = g_devices[index]; + if (strcmp(desc.adapterName, adaptName) == 0) { + dev = &desc; + break; + } + } + if (dev == nullptr) { + std::cout << "Input device id is wrong." << std::endl; + FindAudioDevice(); + return ERR_DH_AUDIO_HDF_FAIL; + } + if (g_manager == nullptr) { + return ERR_DH_AUDIO_HDF_FAIL; + } + if (g_adapter == nullptr) { + int32_t ret = g_manager->LoadAdapter(g_manager, dev, &g_adapter); + if (ret != DH_SUCCESS || g_adapter == nullptr) { + std::cout << "Load audio device failed, ret: " << ret << std::endl; + return ERR_DH_AUDIO_HDF_FAIL; + } + } + std::cout << "Load audio device success." << std::endl; + return DH_SUCCESS; +} + +std::string OpenMic() +{ + if (g_micStatus != DEVICE_IDLE) { + return "Mic device is already opened."; + } + if (LoadMicDev() != DH_SUCCESS) { + return "Load audio device failed."; + } + + AudioDeviceDescriptor captureDesc; + captureDesc.pins = AudioPortPin::PIN_IN_MIC; + captureDesc.desc = nullptr; + AudioSampleAttributes captureAttr; + captureAttr.type = AUDIO_IN_MEDIA; + captureAttr.interleaved = CAPTURE_INTER_LEAVED; + captureAttr.streamId = CAPTURE_STREAM_ID; + captureAttr.channelCount = CAPTURE_CHANNEL_MASK; + captureAttr.sampleRate = AUDIO_SAMPLE_RATE; + captureAttr.format = AudioFormat::AUDIO_FORMAT_TYPE_PCM_16_BIT; + int32_t ret = g_adapter->CreateCapture(g_adapter, &captureDesc, &captureAttr, &g_capture); + if (ret != DH_SUCCESS || g_capture == nullptr) { + return "Open MIC device failed."; + } + g_micStatus = DEVICE_OPEN; + return "true"; +} + +static void ReadStreamWait(const int64_t &startTime) +{ + int64_t endTime = GetNowTimeUs(); + int32_t passTime = endTime - startTime; + + if (passTime > AUDIO_FRAME_TIME_INTERFAL_DEFAULT) { + return; + } + int64_t remainTime = AUDIO_FRAME_TIME_INTERFAL_DEFAULT - passTime; + std::this_thread::sleep_for(std::chrono::microseconds(remainTime)); +} + +static void Capture() +{ + if (g_capture == nullptr) { + std::cout << "MIC device is null." << std::endl; + return; + } + if (pthread_setname_np(pthread_self(), CAPTURE_THREAD) != DH_SUCCESS) { + std::cout << "Capture thread setname failed." << std::endl; + } + std::cout << "Capturing thread started." << std::endl; + g_capture->control.Start((AudioHandle)g_capture); + g_micStatus = DEVICE_START; + + uint64_t size = 0; + while (g_micStatus == DEVICE_START) { + uint8_t *data[RENDER_FRAME_SIZE]; + int64_t startTime = GetNowTimeUs(); + int32_t ret = g_capture->CaptureFrame(g_capture, data, RENDER_FRAME_SIZE, &size); + if (ret != DH_SUCCESS) { + std::cout << "CaptureFrame failed, ret: " << ret << std::endl; + return; + } + fwrite(data, 1, RENDER_FRAME_SIZE, g_micFile); + g_micFrameNum++; + ReadStreamWait(startTime); + } + std::cout << "Capturing thread stopped." << std::endl; +} + +std::string StartCapture() +{ + if (g_micStatus == DEVICE_IDLE) { + return "Mic device is not opened, start capture failed."; + } + + if (g_micStatus == DEVICE_OPEN) { + g_micFile = fopen(MIC_FILE_PATH, "ab+"); + if (g_micFile == nullptr) { + return "Open pcm file failed."; + } + g_capingThread = std::thread(Capture); + return "true"; + } + + if (g_micStatus == DEVICE_START) { + return "Mic device is already started."; + } + + if (g_micStatus == DEVICE_STOP) { + g_capingThread = std::thread(Capture); + } + return "true"; +} + +std::string StopCapture() +{ + if (g_capture == nullptr) { + return "MIC device is null."; + } + + if (g_micStatus == DEVICE_IDLE) { + return "Mic device is not opened."; + } + + if (g_micStatus == DEVICE_OPEN) { + return "Mic device is not started."; + } + + if (g_micStatus == DEVICE_STOP) { + return "Mic device is already started."; + } + + g_micStatus = DEVICE_STOP; + if (g_capingThread.joinable()) { + g_capingThread.join(); + } + g_capture->control.Stop((AudioHandle)g_capture); + return "true"; +} + +std::string CloseMic() +{ + if (g_micStatus == DEVICE_IDLE) { + return "Mic device is not opened."; + } + + if (g_micStatus == DEVICE_START) { + StopCapture(); + } + + int32_t ret = g_adapter->DestroyCapture(g_adapter, g_capture); + if (ret != DH_SUCCESS) { + return "Close mic failed."; + } + if (g_spkStatus == DEVICE_IDLE) { + g_manager->UnloadAdapter(g_manager, g_adapter); + g_adapter = nullptr; + } + if (g_micFile != nullptr) { + fclose(g_micFile); + g_micFile = nullptr; + } + g_micStatus = DEVICE_IDLE; + return "true"; +} + +std::string SetVolume(std::string vol) +{ + if (g_spkStatus == DEVICE_IDLE) { + return "Speaker is not opened, can not set volume."; + } + int32_t volInt = std::stoi(vol); + if (volInt < VOLUME_MIN || volInt > VOLUME_MAX) { + return "Volume is invalid"; + } + enum AudioExtParamKey key = AudioExtParamKey::AUDIO_EXT_PARAM_KEY_VOLUME; + std::string condition = "EVENT_TYPE=1;VOLUME_GROUP_ID=1;AUDIO_VOLUME_TYPE=1;"; + int32_t ret = g_adapter->SetExtraParams(g_adapter, key, condition.c_str(), vol.c_str()); + if (ret != DH_SUCCESS) { + return "Set volume failed"; + } + return "true"; +} + +std::string GetVolume() +{ + if (g_spkStatus == DEVICE_IDLE) { + return "Speaker is not opened, can not get volume."; + } + enum AudioExtParamKey key = AudioExtParamKey::AUDIO_EXT_PARAM_KEY_VOLUME; + std::string condition = "EVENT_TYPE=1;VOLUME_GROUP_ID=1;AUDIO_VOLUME_TYPE=1;"; + char vol[VOLUME_BIT]; + int32_t ret = g_adapter->GetExtraParams(g_adapter, key, condition.c_str(), vol, VOLUME_BIT); + if (ret != DH_SUCCESS) { + return "Get Volume failed."; + } + std::string volStr(vol); + return "true"; +} diff --git a/hdf_service/distributed_audio/distributedaudiotest/distributed_audio_test.h b/hdf_service/distributed_audio/distributedaudiotest/distributed_audio_test.h new file mode 100644 index 0000000000000000000000000000000000000000..323d0745c7615267705e177a87b8c7f4a0d61e6b --- /dev/null +++ b/hdf_service/distributed_audio/distributedaudiotest/distributed_audio_test.h @@ -0,0 +1,92 @@ +/* + * 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 DISTRIBUTED_AUDIO_TEST_H +#define DISTRIBUTED_AUDIO_TEST_H + +#include +#include +#include +#include +#include +#include +#include + +#include "audio_adapter.h" +#include "audio_manager.h" +#include "audio_types.h" +#include "daudio_errcode.h" + +const char DEV_TYPE_SPK = '1'; +const char DEV_TYPE_MIC = '2'; +const char SPK_FILE_PATH[128] = "/data/test.wav"; +const char MIC_FILE_PATH[128] = "/data/mic.pcm"; +constexpr int32_t TYPE_OFFSET = 12; +constexpr int32_t AUDIO_SAMPLE_RATE = 48000; +constexpr int32_t VOLUME_MIN = 0; +constexpr int32_t VOLUME_MAX = 15; +constexpr int32_t VOLUME_BIT = 3; +constexpr int32_t RENDER_FRAME_SIZE = 4096; +constexpr int32_t RENDER_INTER_LEAVED = 1; +constexpr int32_t RENDER_STREAM_ID = 0; +constexpr int32_t RENDER_CHANNEL_MASK = 2; +constexpr int32_t CAPTURE_INTER_LEAVED = 1; +constexpr int32_t CAPTURE_STREAM_ID = 2; +constexpr int32_t CAPTURE_CHANNEL_MASK = 2; +constexpr int32_t MILLISECOND_PER_SECOND = 1000; +constexpr int64_t AUDIO_FRAME_TIME_INTERFAL_DEFAULT = 21333; +constexpr int32_t CMD_EXECUTING_RETURN_LENGHT_MAX = 500; + +typedef enum { + DEVICE_IDLE = 0, + DEVICE_OPEN = 1, + DEVICE_START = 2, + DEVICE_STOP = 3, +} DeviceStatus; + +struct WAV_HEADER { + /* RIFF Chunk Descriptor */ + uint8_t riff[4] = {'R', 'I', 'F', 'F'}; + uint32_t chunkSize = 0; + uint8_t wave[4] = {'W', 'A', 'V', 'E'}; + /* "fmt" sub-chunk */ + uint8_t fmt[4] = {'f', 'm', 't', ' '}; + uint32_t subchunk1Size = 16; + uint16_t audioFormat = 1; + uint16_t numOfChan = 2; + uint32_t samplesPerSec = 44100; + uint32_t bytesPerSec = 176400; + uint16_t blockAlign = 2; + uint16_t bitsPerSample = 16; + /* "data" sub-chunk */ + uint8_t subchunk2ID[4] = {'d', 'a', 't', 'a'}; + uint32_t subchunk2Size = 0; +}; +using WavHdr = struct WAV_HEADER; + +int32_t InitTestDemo(void); +int32_t FindAudioDevice(void); +std::string OpenSpk(); +std::string CloseSpk(); +std::string OpenMic(); +std::string CloseMic(); +std::string StartRender(); +std::string StopRender(); +std::string StartCapture(); +std::string StopCapture(); +std::string SetVolume(std::string vol); +std::string GetVolume(); + +#endif \ No newline at end of file