From b69a130b9a4a70835e2a23e849001834c71d00e1 Mon Sep 17 00:00:00 2001 From: wangyi Date: Wed, 3 Sep 2025 21:41:54 +0800 Subject: [PATCH] tts inject Signed-off-by: wangyi --- .../native/audioutils/include/audio_utils.h | 12 +- .../native/audioutils/src/audio_utils.cpp | 45 ++ .../unittest/audio_utils_second_unit_test.cpp | 245 ++++++ .../domain/pipe/include/audio_pipe_selector.h | 3 + .../include/audio_policy_config_manager.h | 2 + .../domain/pipe/src/audio_pipe_selector.cpp | 20 +- .../pipe/src/audio_policy_config_manager.cpp | 19 + .../src/audio_pipe_selector_unit_test.cpp | 89 +++ ...udio_policy_service_thirdext_unit_test.cpp | 116 +++ services/audio_service/BUILD.gn | 14 +- .../common/include/format_converter.h | 46 ++ .../common/include/i_audio_process_stream.h | 29 + .../common/src/format_converter.cpp | 105 +++ .../server/include/audio_endpoint.h | 6 +- .../server/include/audio_endpoint_private.h | 43 +- .../server/include/audio_injector_service.h | 5 +- .../server/include/audio_process_in_server.h | 12 + .../server/include/audio_service.h | 3 +- .../server/src/audio_endpoint.cpp | 286 ++++--- .../server/src/audio_endpoint_performance.cpp | 3 +- .../server/src/audio_injector_service.cpp | 7 +- .../server/src/audio_process_in_server.cpp | 161 ++++ .../server/src/audio_service.cpp | 27 +- services/audio_service/test/unittest/BUILD.gn | 6 + .../include/audio_endpoint_unit_test.h | 1 + .../src/audio_endpoint_plus_unit_test.cpp | 284 ++----- .../src/audio_endpoint_unit_test.cpp | 469 ++++++++++- .../audio_process_in_server_unit_test.cpp | 745 ++++++++++++++++++ .../test/unittest/audio_service_unit_test.cpp | 30 +- .../unittest/format_converter_unit_test.cpp | 371 +++++++++ .../renderer_in_server_unit_test/BUILD.gn | 3 + .../audio_service_fuzzer.cpp | 10 +- 32 files changed, 2845 insertions(+), 372 deletions(-) diff --git a/frameworks/native/audioutils/include/audio_utils.h b/frameworks/native/audioutils/include/audio_utils.h index 7868f5db8e..50491912e6 100644 --- a/frameworks/native/audioutils/include/audio_utils.h +++ b/frameworks/native/audioutils/include/audio_utils.h @@ -40,6 +40,8 @@ #define AUDIO_NS_PER_MILLISECOND 1000000 #define AUDIO_NS_PER_SECOND ((uint64_t)1000000000) +#define UINT32_INVALID_VALUE 0xFFFFFFFF + #define FLOAT_EPS 1e-9f #define OFFSET_BIT_24 3 #define BIT_DEPTH_TWO 2 @@ -51,7 +53,6 @@ namespace OHOS { namespace AudioStandard { const uint32_t STRING_BUFFER_SIZE = 4096; const size_t MILLISECOND_PER_SECOND = 1000; -const int32_t GET_EXTRA_PARAM_LEN = 200; const uint32_t AUDIO_ID = 1041; // Ringer or alarmer dual tone @@ -594,6 +595,15 @@ std::list> FromIpcInterrupts( const std::vector> &from); std::string GetBundleNameByToken(const uint32_t &tokenIdNum); + +std::string ConvertToStringForFormat(const AudioSampleFormat format); +std::string ConvertToStringForSampleRate(const AudioSamplingRate sampleRate); +std::string ConvertToStringForChannel(const AudioChannel channel); + +uint8_t* ReallocVectorBufferAndClear(std::vector &buffer, const size_t bufLength); +bool IsInjectEnable(); +void SetInjectEnable(bool injectSwitch); + } // namespace AudioStandard } // namespace OHOS #endif // AUDIO_UTILS_H diff --git a/frameworks/native/audioutils/src/audio_utils.cpp b/frameworks/native/audioutils/src/audio_utils.cpp index 68455b485b..caf238889e 100644 --- a/frameworks/native/audioutils/src/audio_utils.cpp +++ b/frameworks/native/audioutils/src/audio_utils.cpp @@ -2086,6 +2086,51 @@ std::string GetBundleNameByToken(const uint32_t &tokenIdNum) return tokenInfo.processName; } } + +static std::unordered_map g_formatToStringMap = { + {SAMPLE_U8, "s8"}, + {SAMPLE_S16LE, "s16le"}, + {SAMPLE_S24LE, "s24le"}, + {SAMPLE_S32LE, "s32le"}, + {SAMPLE_F32LE, "f32le"} +}; +std::string ConvertToStringForFormat(const AudioSampleFormat format) +{ + std::string formatStr = "s16le"; + auto it = g_formatToStringMap.find(format); + if (it != g_formatToStringMap.end()) { + formatStr = it->second; + } + return formatStr; +} + +std::string ConvertToStringForSampleRate(const AudioSamplingRate sampleRate) +{ + return std::to_string(static_cast(sampleRate)); +} + +std::string ConvertToStringForChannel(const AudioChannel channel) +{ + return std::to_string(static_cast(channel)); +} + +uint8_t* ReallocVectorBufferAndClear(std::vector &buffer, const size_t bufLength) +{ + buffer.assign(bufLength, 0); + return buffer.data(); +} + +bool g_injectSwitch = system::GetBoolParameter("const.multimedia.audio.inject", false); +bool IsInjectEnable() +{ + return g_injectSwitch; +} + +void SetInjectEnable(bool injectSwitch) +{ + g_injectSwitch = injectSwitch; +} + } // namespace AudioStandard } // namespace OHOS diff --git a/frameworks/native/audioutils/test/unittest/audio_utils_second_unit_test.cpp b/frameworks/native/audioutils/test/unittest/audio_utils_second_unit_test.cpp index 89adcbc7ce..4623022360 100644 --- a/frameworks/native/audioutils/test/unittest/audio_utils_second_unit_test.cpp +++ b/frameworks/native/audioutils/test/unittest/audio_utils_second_unit_test.cpp @@ -334,5 +334,250 @@ HWTEST(AudioUtilsUnitTest, CalculatePcmSizeFromDurationCeiling, TestSize.Level1) EXPECT_EQ(Util::CalculatePcmSizeFromDurationCeiling(20ms + 1ns, 48000, 4), 3844); } + +/** + * @tc.name : Test ConvertToStringForFormat API + * @tc.type : FUNC + * @tc.number: ConvertToStringForFormat_001 + * @tc.desc : Test ConvertToStringForFormat with all supported sample formats. + */ +HWTEST(AudioUtilsUnitTest, ConvertToStringForFormat_001, TestSize.Level1) +{ + EXPECT_EQ(ConvertToStringForFormat(SAMPLE_U8), "s8"); + EXPECT_EQ(ConvertToStringForFormat(SAMPLE_S16LE), "s16le"); + EXPECT_EQ(ConvertToStringForFormat(SAMPLE_S24LE), "s24le"); + EXPECT_EQ(ConvertToStringForFormat(SAMPLE_S32LE), "s32le"); + EXPECT_EQ(ConvertToStringForFormat(SAMPLE_F32LE), "f32le"); +} + +/** + * @tc.name : Test ConvertToStringForFormat API with unsupported format + * @tc.type : FUNC + * @tc.number: ConvertToStringForFormat_002 + * @tc.desc : Test ConvertToStringForFormat with unsupported sample format returns default value. + */ +HWTEST(AudioUtilsUnitTest, ConvertToStringForFormat_002, TestSize.Level1) +{ + // Test with unsupported format (assuming 999 is not in the map) + AudioSampleFormat unsupportedFormat = static_cast(999); + EXPECT_EQ(ConvertToStringForFormat(unsupportedFormat), "s16le"); +} + +/** + * @tc.name : Test ConvertToStringForSampleRate API + * @tc.type : FUNC + * @tc.number: ConvertToStringForSampleRate_001 + * @tc.desc : Test ConvertToStringForSampleRate with various sampling rates. + */ +HWTEST(AudioUtilsUnitTest, ConvertToStringForSampleRate_001, TestSize.Level1) +{ + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_8000), "8000"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_11025), "11025"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_12000), "12000"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_16000), "16000"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_22050), "22050"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_24000), "24000"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_32000), "32000"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_44100), "44100"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_48000), "48000"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_64000), "64000"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_88200), "88200"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_96000), "96000"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_176400), "176400"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_192000), "192000"); + EXPECT_EQ(ConvertToStringForSampleRate(SAMPLE_RATE_384000), "384000"); +} + +/** + * @tc.name : Test ConvertToStringForSampleRate API with custom values + * @tc.type : FUNC + * @tc.number: ConvertToStringForSampleRate_002 + * @tc.desc : Test ConvertToStringForSampleRate with custom sampling rate values. + */ +HWTEST(AudioUtilsUnitTest, ConvertToStringForSampleRate_002, TestSize.Level1) +{ + // Test with some arbitrary values to ensure conversion works correctly + AudioSamplingRate customRate1 = static_cast(22050); + AudioSamplingRate customRate2 = static_cast(32000); + AudioSamplingRate customRate3 = static_cast(96000); + + EXPECT_EQ(ConvertToStringForSampleRate(customRate1), "22050"); + EXPECT_EQ(ConvertToStringForSampleRate(customRate2), "32000"); + EXPECT_EQ(ConvertToStringForSampleRate(customRate3), "96000"); +} + +/** + * @tc.name : Test ConvertToStringForChannel API + * @tc.type : FUNC + * @tc.number: ConvertToStringForChannel_001 + * @tc.desc : Test ConvertToStringForChannel with various channel configurations. + */ +HWTEST(AudioUtilsUnitTest, ConvertToStringForChannel_001, TestSize.Level1) +{ + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_UNKNOW), "0"); + EXPECT_EQ(ConvertToStringForChannel(MONO), "1"); + EXPECT_EQ(ConvertToStringForChannel(STEREO), "2"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_3), "3"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_4), "4"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_5), "5"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_6), "6"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_7), "7"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_8), "8"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_9), "9"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_10), "10"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_11), "11"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_12), "12"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_13), "13"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_14), "14"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_15), "15"); + EXPECT_EQ(ConvertToStringForChannel(CHANNEL_16), "16"); +} + +/** + * @tc.name : Test ConvertToStringForChannel API with custom values + * @tc.type : FUNC + * @tc.number: ConvertToStringForChannel_002 + * @tc.desc : Test ConvertToStringForChannel with custom channel values. + */ +HWTEST(AudioUtilsUnitTest, ConvertToStringForChannel_002, TestSize.Level1) +{ + // Test with some arbitrary channel counts beyond the defined enums + AudioChannel customChannel1 = static_cast(17); + AudioChannel customChannel2 = static_cast(24); + AudioChannel customChannel3 = static_cast(32); + + EXPECT_EQ(ConvertToStringForChannel(customChannel1), "17"); + EXPECT_EQ(ConvertToStringForChannel(customChannel2), "24"); + EXPECT_EQ(ConvertToStringForChannel(customChannel3), "32"); +} + +/** + * @tc.name : Test ReallocVectorBufferAndClear API with zero length + * @tc.type : FUNC + * @tc.number: ReallocVectorBufferAndClear_001 + * @tc.desc : Test ReallocVectorBufferAndClear with zero buffer length. + */ +HWTEST(AudioUtilsUnitTest, ReallocVectorBufferAndClear_001, TestSize.Level1) +{ + std::vector buffer = {1, 2, 3, 4, 5}; + + uint8_t* result = ReallocVectorBufferAndClear(buffer, 0); + + EXPECT_EQ(buffer.size(), 0); + EXPECT_EQ(result, buffer.data()); +} + +/** + * @tc.name : Test ReallocVectorBufferAndClear API with positive length + * @tc.type : FUNC + * @tc.number: ReallocVectorBufferAndClear_002 + * @tc.desc : Test ReallocVectorBufferAndClear with positive buffer length. + */ +HWTEST(AudioUtilsUnitTest, ReallocVectorBufferAndClear_002, TestSize.Level1) +{ + std::vector buffer = {1, 2, 3, 4, 5}; + const size_t newLength = 10; + + uint8_t* result = ReallocVectorBufferAndClear(buffer, newLength); + + EXPECT_EQ(buffer.size(), newLength); + EXPECT_EQ(result, buffer.data()); + + // Verify all elements are cleared to zero + for (size_t i = 0; i < newLength; i++) { + EXPECT_EQ(buffer[i], 0); + } +} + +/** + * @tc.name : Test ReallocVectorBufferAndClear API with larger length + * @tc.type : FUNC + * @tc.number: ReallocVectorBufferAndClear_003 + * @tc.desc : Test ReallocVectorBufferAndClear with larger buffer length than original. + */ +HWTEST(AudioUtilsUnitTest, ReallocVectorBufferAndClear_003, TestSize.Level1) +{ + std::vector buffer = {1, 2, 3}; + const size_t newLength = 8; + + uint8_t* result = ReallocVectorBufferAndClear(buffer, newLength); + + EXPECT_EQ(buffer.size(), newLength); + EXPECT_EQ(result, buffer.data()); + + // Verify all elements are cleared to zero + for (size_t i = 0; i < newLength; i++) { + EXPECT_EQ(buffer[i], 0); + } +} + +/** + * @tc.name : Test ReallocVectorBufferAndClear API with smaller length + * @tc.type : FUNC + * @tc.number: ReallocVectorBufferAndClear_004 + * @tc.desc : Test ReallocVectorBufferAndClear with smaller buffer length than original. + */ +HWTEST(AudioUtilsUnitTest, ReallocVectorBufferAndClear_004, TestSize.Level1) +{ + std::vector buffer = {1, 2, 3, 4, 5}; + const size_t newLength = 2; + + uint8_t* result = ReallocVectorBufferAndClear(buffer, newLength); + + EXPECT_EQ(buffer.size(), newLength); + EXPECT_EQ(result, buffer.data()); + + // Verify all elements are cleared to zero + for (size_t i = 0; i < newLength; i++) { + EXPECT_EQ(buffer[i], 0); + } +} + +/** + * @tc.name : Test ReallocVectorBufferAndClear API return value + * @tc.type : FUNC + * @tc.number: ReallocVectorBufferAndClear_005 + * @tc.desc : Test that ReallocVectorBufferAndClear returns correct pointer. + */ +HWTEST(AudioUtilsUnitTest, ReallocVectorBufferAndClear_005, TestSize.Level1) +{ + std::vector buffer; + const size_t newLength = 5; + + uint8_t* result = ReallocVectorBufferAndClear(buffer, newLength); + + EXPECT_EQ(result, buffer.data()); + EXPECT_NE(result, nullptr); + EXPECT_EQ(buffer.size(), newLength); +} + +/** + * @tc.name : Test ReallocVectorBufferAndClear API with typical audio buffer sizes + * @tc.type : FUNC + * @tc.number: ReallocVectorBufferAndClear_006 + * @tc.desc : Test ReallocVectorBufferAndClear with typical audio buffer sizes. + */ +HWTEST(AudioUtilsUnitTest, ReallocVectorBufferAndClear_006, TestSize.Level1) +{ + std::vector buffer; + + // Test with typical audio buffer sizes (frames * channels * sample size) + uint8_t* result1 = ReallocVectorBufferAndClear(buffer, 1024); // 1KB buffer + EXPECT_EQ(buffer.size(), 1024); + EXPECT_EQ(result1, buffer.data()); + + uint8_t* result2 = ReallocVectorBufferAndClear(buffer, 4096); // 4KB buffer + EXPECT_EQ(buffer.size(), 4096); + EXPECT_EQ(result2, buffer.data()); + + uint8_t* result3 = ReallocVectorBufferAndClear(buffer, 16384); // 16KB buffer + EXPECT_EQ(buffer.size(), 16384); + EXPECT_EQ(result3, buffer.data()); + + // Verify all elements are cleared to zero + for (size_t i = 0; i < buffer.size(); i++) { + EXPECT_EQ(buffer[i], 0); + } +} } // namespace AudioStandard } // namespace OHOS \ No newline at end of file diff --git a/services/audio_policy/server/domain/pipe/include/audio_pipe_selector.h b/services/audio_policy/server/domain/pipe/include/audio_pipe_selector.h index 3410eda2a0..191630afa6 100644 --- a/services/audio_policy/server/domain/pipe/include/audio_pipe_selector.h +++ b/services/audio_policy/server/domain/pipe/include/audio_pipe_selector.h @@ -19,6 +19,7 @@ #include "audio_pipe_manager.h" #include "audio_stream_info.h" #include "audio_policy_config_manager.h" +#include "audio_concurrency_parser.h" namespace OHOS { namespace AudioStandard { @@ -39,6 +40,8 @@ private: std::shared_ptr streamPropInfo); void ScanPipeListForStreamDesc(std::vector> &pipeInfoList, std::shared_ptr streamDesc); + void UpdateProcessConcurrency(AudioPipeType existingPipe, AudioPipeType commingPipe, + ConcurrencyAction &action); bool ProcessConcurrency(std::shared_ptr existingStream, std::shared_ptr incomingStream, std::vector> &streamsToMove); diff --git a/services/audio_policy/server/domain/pipe/include/audio_policy_config_manager.h b/services/audio_policy/server/domain/pipe/include/audio_policy_config_manager.h index 4e0ac656b5..4960bce42d 100644 --- a/services/audio_policy/server/domain/pipe/include/audio_policy_config_manager.h +++ b/services/audio_policy/server/domain/pipe/include/audio_policy_config_manager.h @@ -109,6 +109,8 @@ public: { } private: + void UpdateStreamSampleInfo(std::shared_ptr desc, + AudioStreamInfo &streamInfo); void UpdateBasicStreamInfo(std::shared_ptr desc, std::shared_ptr pipeInfo, AudioStreamInfo &streamInfo); void GetStreamPropInfoForRecord(std::shared_ptr desc, diff --git a/services/audio_policy/server/domain/pipe/src/audio_pipe_selector.cpp b/services/audio_policy/server/domain/pipe/src/audio_pipe_selector.cpp index 34fc63c499..2625299c35 100644 --- a/services/audio_policy/server/domain/pipe/src/audio_pipe_selector.cpp +++ b/services/audio_policy/server/domain/pipe/src/audio_pipe_selector.cpp @@ -381,13 +381,24 @@ bool AudioPipeSelector::IsSameAdapter(std::shared_ptr str return false; } +void AudioPipeSelector::UpdateProcessConcurrency(AudioPipeType existingPipe, AudioPipeType commingPipe, + ConcurrencyAction &action) +{ + /* becasue call in indicate voip and cell, so can't modify xml */ + CHECK_AND_RETURN(IsInjectEnable() && action != PLAY_BOTH); + if (existingPipe == PIPE_TYPE_CALL_IN && commingPipe == PIPE_TYPE_CALL_IN) { + action = PLAY_BOTH; + } +} + bool AudioPipeSelector::ProcessConcurrency(std::shared_ptr existingStream, std::shared_ptr incomingStream, std::vector> &streamsToMove) { - ConcurrencyAction action = action = AudioStreamCollector::GetAudioStreamCollector().GetConcurrencyAction( - GetPipeType(existingStream->routeFlag_, existingStream->audioMode_), - GetPipeType(incomingStream->routeFlag_, incomingStream->audioMode_)); + AudioPipeType existingPipe = GetPipeType(existingStream->routeFlag_, existingStream->audioMode_); + AudioPipeType commingPipe = GetPipeType(incomingStream->routeFlag_, incomingStream->audioMode_); + ConcurrencyAction action = AudioStreamCollector::GetAudioStreamCollector().GetConcurrencyAction( + existingPipe, commingPipe); action = IsSameAdapter(existingStream, incomingStream) ? action : PLAY_BOTH; // No running offload can not concede incoming special pipe if (action == CONCEDE_INCOMING && existingStream->IsNoRunningOffload()) { @@ -400,6 +411,9 @@ bool AudioPipeSelector::ProcessConcurrency(std::shared_ptrGetSessionId(), existingStream->GetRoute(), incomingStream->GetSessionId(), incomingStream->GetRoute()); + /* temporary handle */ + UpdateProcessConcurrency(existingPipe, commingPipe, action); + bool isUpdate = false; switch (action) { case PLAY_BOTH: diff --git a/services/audio_policy/server/domain/pipe/src/audio_policy_config_manager.cpp b/services/audio_policy/server/domain/pipe/src/audio_policy_config_manager.cpp index 0b8fc42f29..577125d814 100644 --- a/services/audio_policy/server/domain/pipe/src/audio_policy_config_manager.cpp +++ b/services/audio_policy/server/domain/pipe/src/audio_policy_config_manager.cpp @@ -720,6 +720,23 @@ void AudioPolicyConfigManager::GetStreamPropInfo(std::shared_ptr desc, + AudioStreamInfo &streamInfo) +{ + CHECK_AND_RETURN(IsInjectEnable()); + + if (desc->routeFlag_ != (AUDIO_INPUT_FLAG_VOIP | AUDIO_INPUT_FLAG_FAST)) { + return; + } + + /* voip fast support resample, but hal only support 16k or 48k, so need config hal + 16k or 48k first here, then do resample in endpoint */ + if ((desc->streamInfo_.samplingRate != SAMPLE_RATE_16000) && + (desc->streamInfo_.samplingRate != SAMPLE_RATE_48000)) { + desc->streamInfo_.samplingRate = SAMPLE_RATE_48000; + } +} + void AudioPolicyConfigManager::UpdateBasicStreamInfo(std::shared_ptr desc, std::shared_ptr pipeInfo, AudioStreamInfo &streamInfo) { @@ -737,6 +754,8 @@ void AudioPolicyConfigManager::UpdateBasicStreamInfo(std::shared_ptrstreamInfo_.channels == MONO ? STEREO : desc->streamInfo_.channels; } + UpdateStreamSampleInfo(desc, streamInfo); + if (pipeInfo->streamPropInfos_.empty()) { AUDIO_WARNING_LOG("streamPropInfos_ is empty!"); return; diff --git a/services/audio_policy/test/unittest/audio_pipe_selector_unit_test/src/audio_pipe_selector_unit_test.cpp b/services/audio_policy/test/unittest/audio_pipe_selector_unit_test/src/audio_pipe_selector_unit_test.cpp index 4dab190fb7..00e4036e2c 100644 --- a/services/audio_policy/test/unittest/audio_pipe_selector_unit_test/src/audio_pipe_selector_unit_test.cpp +++ b/services/audio_policy/test/unittest/audio_pipe_selector_unit_test/src/audio_pipe_selector_unit_test.cpp @@ -594,6 +594,95 @@ HWTEST_F(AudioPipeSelectorUnitTest, ProcessConcurrency_001, TestSize.Level4) EXPECT_TRUE(ret); } +/** + * @tc.name: UpdateProcessConcurrency_001 + * @tc.desc: Test UpdateProcessConcurrency with CALL_IN pipes and PLAY_BOTH action modification. + * @tc.type: FUNC + * @tc.require: #I5Y4MZ + */ +HWTEST_F(AudioPipeSelectorUnitTest, UpdateProcessConcurrency_001, TestSize.Level4) +{ + auto audioPipeSelector = AudioPipeSelector::GetPipeSelector(); + AudioPipeType existingPipe = PIPE_TYPE_CALL_IN; + AudioPipeType commingPipe = PIPE_TYPE_CALL_IN; + ConcurrencyAction action = CONCEDE_INCOMING; // Initial action + + SetInjectEnable(true); + audioPipeSelector->UpdateProcessConcurrency(existingPipe, commingPipe, action); + + // Verify that action is updated to PLAY_BOTH when both pipes are CALL_IN and injection is enabled + EXPECT_EQ(action, PLAY_BOTH); +} + +/** + * @tc.name: UpdateProcessConcurrency_002 + * @tc.desc: Test UpdateProcessConcurrency with different pipe types and no action modification. + * @tc.type: FUNC + * @tc.require: #I5Y4MZ + */ +HWTEST_F(AudioPipeSelectorUnitTest, UpdateProcessConcurrency_002, TestSize.Level4) +{ + auto audioPipeSelector = AudioPipeSelector::GetPipeSelector(); + AudioPipeType existingPipe = PIPE_TYPE_LOWLATENCY_OUT; + AudioPipeType commingPipe = PIPE_TYPE_CALL_IN; + ConcurrencyAction originalAction = CONCEDE_EXISTING; + ConcurrencyAction action = originalAction; + + SetInjectEnable(true); + audioPipeSelector->UpdateProcessConcurrency(existingPipe, commingPipe, action); + + // Verify that action remains unchanged when pipe types are different + EXPECT_EQ(action, originalAction); +} + +/** + * @tc.name: UpdateProcessConcurrency_003 + * @tc.desc: Test UpdateProcessConcurrency with action already set to PLAY_BOTH and no modification. + * @tc.type: FUNC + * @tc.require: #I5Y4MZ + */ +HWTEST_F(AudioPipeSelectorUnitTest, UpdateProcessConcurrency_003, TestSize.Level4) +{ + auto audioPipeSelector = AudioPipeSelector::GetPipeSelector(); + AudioPipeType existingPipe = PIPE_TYPE_CALL_IN; + AudioPipeType commingPipe = PIPE_TYPE_CALL_IN; + ConcurrencyAction originalAction = PLAY_BOTH; + ConcurrencyAction action = originalAction; + + SetInjectEnable(true); + audioPipeSelector->UpdateProcessConcurrency(existingPipe, commingPipe, action); + + // Verify that action remains PLAY_BOTH when it's already set + EXPECT_EQ(action, originalAction); +} + +/** + * @tc.name: UpdateProcessConcurrency_004 + * @tc.desc: Test UpdateProcessConcurrency with various CALL_IN scenarios and action modification. + * @tc.type: FUNC + * @tc.require: #I5Y4MZ + */ +HWTEST_F(AudioPipeSelectorUnitTest, UpdateProcessConcurrency_004, TestSize.Level4) +{ + auto audioPipeSelector = AudioPipeSelector::GetPipeSelector(); + SetInjectEnable(true); + + // Test case 1: Both pipes are CALL_IN, injection enabled, action should be updated to PLAY_BOTH + ConcurrencyAction action = CONCEDE_INCOMING; + audioPipeSelector->UpdateProcessConcurrency(PIPE_TYPE_CALL_IN, PIPE_TYPE_CALL_IN, action); + EXPECT_EQ(action, PLAY_BOTH); + + // Test case 2: Different pipe types, action should remain unchanged + action = CONCEDE_EXISTING; + audioPipeSelector->UpdateProcessConcurrency(PIPE_TYPE_CALL_IN, PIPE_TYPE_LOWLATENCY_OUT, action); + EXPECT_EQ(action, CONCEDE_EXISTING); + + // Test case 3: Same pipe types but not CALL_IN, action should remain unchanged + action = CONCEDE_INCOMING; + audioPipeSelector->UpdateProcessConcurrency(PIPE_TYPE_LOWLATENCY_OUT, PIPE_TYPE_LOWLATENCY_OUT, action); + EXPECT_EQ(action, CONCEDE_INCOMING); +} + /** * @tc.name: AudioPipeSelectorUnitTest_MoveStreamsToNormalPipes_001 * @tc.number: MoveStreamsToNormalPipes_001 diff --git a/services/audio_policy/test/unittest/audio_policy_service_unit_test/src/audio_policy_service_thirdext_unit_test.cpp b/services/audio_policy/test/unittest/audio_policy_service_unit_test/src/audio_policy_service_thirdext_unit_test.cpp index 366c34f708..cf48d1ea29 100644 --- a/services/audio_policy/test/unittest/audio_policy_service_unit_test/src/audio_policy_service_thirdext_unit_test.cpp +++ b/services/audio_policy/test/unittest/audio_policy_service_unit_test/src/audio_policy_service_thirdext_unit_test.cpp @@ -1589,6 +1589,122 @@ HWTEST_F(AudioPolicyServiceFourthUnitTest, UpdateBasicStreamInfo_001, TestSize.L EXPECT_EQ(streamInfo.channels, STEREO); } +/** + * @tc.name : Test UpdateStreamSampleInfo API + * @tc.number: UpdateStreamSampleInfo_001 + * @tc.desc : Test UpdateStreamSampleInfo with non-VOIP_FAST route flag, should return early. + */ +HWTEST_F(AudioPolicyServiceFourthUnitTest, UpdateStreamSampleInfo_001, TestSize.Level1) +{ + AudioPolicyConfigManager &manager = AudioPolicyConfigManager::GetInstance(); + std::shared_ptr desc = std::make_shared(); + AudioStreamInfo streamInfo; + streamInfo.samplingRate = SAMPLE_RATE_44100; + desc->routeFlag_ = AUDIO_INPUT_FLAG_FAST; // Not VOIP | FAST combination + + SetInjectEnable(true); + manager.UpdateStreamSampleInfo(desc, streamInfo); + + // Should return early without modifying sampling rate + EXPECT_EQ(desc->streamInfo_.samplingRate, SAMPLE_RATE_44100); +} + +/** + * @tc.name : Test UpdateStreamSampleInfo API + * @tc.number: UpdateStreamSampleInfo_002 + * @tc.desc : Test UpdateStreamSampleInfo with VOIP_FAST route and 16000 sampling rate, should not modify. + */ +HWTEST_F(AudioPolicyServiceFourthUnitTest, UpdateStreamSampleInfo_002, TestSize.Level1) +{ + AudioPolicyConfigManager &manager = AudioPolicyConfigManager::GetInstance(); + std::shared_ptr desc = std::make_shared(); + AudioStreamInfo streamInfo; + streamInfo.samplingRate = SAMPLE_RATE_16000; + desc->routeFlag_ = (AUDIO_INPUT_FLAG_VOIP | AUDIO_INPUT_FLAG_FAST); + + SetInjectEnable(true); + manager.UpdateStreamSampleInfo(desc, streamInfo); + + // Should not modify since it's already 16000 + EXPECT_EQ(desc->streamInfo_.samplingRate, SAMPLE_RATE_16000); +} + +/** + * @tc.name : Test UpdateStreamSampleInfo API + * @tc.number: UpdateStreamSampleInfo_003 + * @tc.desc : Test UpdateStreamSampleInfo with VOIP_FAST route and 48000 sampling rate, should not modify. + */ +HWTEST_F(AudioPolicyServiceFourthUnitTest, UpdateStreamSampleInfo_003, TestSize.Level1) +{ + AudioPolicyConfigManager &manager = AudioPolicyConfigManager::GetInstance(); + std::shared_ptr desc = std::make_shared(); + AudioStreamInfo streamInfo; + streamInfo.samplingRate = SAMPLE_RATE_48000; + desc->routeFlag_ = (AUDIO_INPUT_FLAG_VOIP | AUDIO_INPUT_FLAG_FAST); + + SetInjectEnable(true); + manager.UpdateStreamSampleInfo(desc, streamInfo); + + // Should not modify since it's already 48000 + EXPECT_EQ(desc->streamInfo_.samplingRate, SAMPLE_RATE_48000); +} + +/** + * @tc.name : Test UpdateStreamSampleInfo API + * @tc.number: UpdateStreamSampleInfo_004 + * @tc.desc : Test UpdateStreamSampleInfo with VOIP_FAST route and 44100 sampling rate, should change to 48000. + */ +HWTEST_F(AudioPolicyServiceFourthUnitTest, UpdateStreamSampleInfo_004, TestSize.Level1) +{ + AudioPolicyConfigManager &manager = AudioPolicyConfigManager::GetInstance(); + std::shared_ptr desc = std::make_shared(); + AudioStreamInfo streamInfo; + streamInfo.samplingRate = SAMPLE_RATE_44100; + desc->routeFlag_ = (AUDIO_INPUT_FLAG_VOIP | AUDIO_INPUT_FLAG_FAST); + + SetInjectEnable(true); + manager.UpdateStreamSampleInfo(desc, streamInfo); + + // Should change from 44100 to 48000 + EXPECT_EQ(desc->streamInfo_.samplingRate, SAMPLE_RATE_48000); +} +/** + * @tc.name : Test UpdateStreamSampleInfo API + * @tc.number: UpdateStreamSampleInfo_005 + * @tc.desc : Test UpdateStreamSampleInfo with VOIP_FAST route and various unsupported sampling rates. + */ +HWTEST_F(AudioPolicyServiceFourthUnitTest, UpdateStreamSampleInfo_005, TestSize.Level1) +{ + AudioPolicyConfigManager &manager = AudioPolicyConfigManager::GetInstance(); + + // Test various sampling rates that should be converted to 48000 + std::vector testRates = { + SAMPLE_RATE_8000, // Should change to 48000 + SAMPLE_RATE_11025, // Should change to 48000 + SAMPLE_RATE_12000, // Should change to 48000 + SAMPLE_RATE_22050, // Should change to 48000 + SAMPLE_RATE_24000, // Should change to 48000 + SAMPLE_RATE_64000, // Should change to 48000 + SAMPLE_RATE_88200, // Should change to 48000 + SAMPLE_RATE_176400, // Should change to 48000 + SAMPLE_RATE_192000, // Should change to 48000 + SAMPLE_RATE_384000 // Should change to 48000 + }; + + SetInjectEnable(true); + for (auto rate : testRates) { + std::shared_ptr desc = std::make_shared(); + AudioStreamInfo streamInfo; + streamInfo.samplingRate = rate; + desc->routeFlag_ = (AUDIO_INPUT_FLAG_VOIP | AUDIO_INPUT_FLAG_FAST); + + manager.UpdateStreamSampleInfo(desc, streamInfo); + + // All unsupported rates should be changed to 48000 + EXPECT_EQ(desc->streamInfo_.samplingRate, SAMPLE_RATE_48000); + } +} + /** * @tc.name : Test AudioPolicyConfigManager. * @tc.number: GetDynamicStreamPropInfoFromPipe_001 diff --git a/services/audio_service/BUILD.gn b/services/audio_service/BUILD.gn index 68ff522cf1..332f02e92b 100644 --- a/services/audio_service/BUILD.gn +++ b/services/audio_service/BUILD.gn @@ -353,6 +353,8 @@ config("audio_service_config") { "../../interfaces/inner_api/native/audiocommon/include", "../../interfaces/inner_api/native/audiomanager/include", "../../frameworks/native/audioclock/include", + "../audio_engine/plugin/resample/include", + "../audio_engine/simd", ] cflags = [] @@ -424,8 +426,11 @@ audio_ohos_library("audio_process_service") { configs = [ ":audio_service_config" ] - include_dirs = - [ "../../services/audio_engine/plugin/channel_converter/include" ] + include_dirs = [ + "../../services/audio_engine/plugin/channel_converter/include", + "../audio_engine/plugin/resample/include", + "../audio_engine/simd", + ] deps = [ ":audio_common", @@ -438,6 +443,7 @@ audio_ohos_library("audio_process_service") { "../../frameworks/native/hdiadapter_new:hdiadapter_new", "../audio_engine:audio_engine_manager", "../audio_engine:audio_engine_plugins", + "../audio_engine:audio_engine_utils", "../audio_policy:audio_foundation", ] @@ -533,6 +539,10 @@ audio_ohos_library("audio_service") { configs = [ ":audio_service_config" ] + include_dirs = [ + "../audio_engine/plugin/resample/include", + ] + deps = [ ":audio_common", ":audio_process_service", diff --git a/services/audio_service/common/include/format_converter.h b/services/audio_service/common/include/format_converter.h index 06dade8964..c2b88cc0eb 100644 --- a/services/audio_service/common/include/format_converter.h +++ b/services/audio_service/common/include/format_converter.h @@ -21,6 +21,41 @@ namespace OHOS { namespace AudioStandard { +struct FormatKey { + AudioChannel srcChn; + AudioSampleFormat srcFormat; + + AudioChannel dstChn; + AudioSampleFormat dstFormat; + + bool operator==(const FormatKey& other) const + { + return srcChn == other.srcChn && + srcFormat == other.srcFormat && + dstChn == other.dstChn && + dstFormat == other.dstFormat; + } +}; + +struct FormatKeyHash { + size_t operator()(const FormatKey& key) const + { + constexpr size_t hashOffset = 0x9e3779b9; + auto updateHash = [](size_t seed, size_t hashVal) -> size_t { + return seed ^ (hashVal + hashOffset + (seed << 6) + (seed >> 2)); + }; + + size_t seed = std::hash{}(static_cast(key.srcChn)); + seed = updateHash(seed, std::hash{}(static_cast(key.srcFormat))); + seed = updateHash(seed, std::hash{}(static_cast(key.dstChn))); + seed = updateHash(seed, std::hash{}(static_cast(key.dstFormat))); + return seed; + } +}; + +using FormatHandler = std::function; +using FormatHandlerMap = std::unordered_map; + class FormatConverter { public: static bool DataAccumulationFromVolume(const std::vector &srcDataList, @@ -34,6 +69,8 @@ public: static int32_t S32MonoToS32Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc); static int32_t F32MonoToS32Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc); static int32_t F32StereoToS32Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc); + static int32_t F32StereoToF32Mono(const BufferDesc &srcDesc, const BufferDesc &dstDesc); + static int32_t F32StereoToS16Mono(const BufferDesc &srcDesc, const BufferDesc &dstDesc); static int32_t S16StereoToF32Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc); static int32_t S16StereoToF32Mono(const BufferDesc &srcDesc, const BufferDesc &dstDesc); @@ -41,7 +78,16 @@ public: static int32_t F32StereoToS16Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc); static int32_t S32MonoToS16Mono(std::vector &audioBuffer, std::vector &audioBufferConverted); static int32_t S32StereoToS16Stereo(std::vector &audioBuffer, std::vector &audioBufferConverted); + + static void InitFormatHandlers(); + static FormatHandlerMap &GetFormatHandlers(); +private: + static void InitS16ToFormatHandlers(FormatHandlerMap& handlers); + static void InitF32ToFormatHandlers(FormatHandlerMap& handlers); +private: + static FormatHandlerMap formatHandlers; }; + } // namespace AudioStandard } // namespace OHOS #endif // FORMAT_CONVERTER_H diff --git a/services/audio_service/common/include/i_audio_process_stream.h b/services/audio_service/common/include/i_audio_process_stream.h index 00dede1733..b6560bec42 100644 --- a/services/audio_service/common/include/i_audio_process_stream.h +++ b/services/audio_service/common/include/i_audio_process_stream.h @@ -22,6 +22,30 @@ namespace OHOS { namespace AudioStandard { + +struct AudioCaptureDataProcParams { + AudioCaptureDataProcParams( + const BufferDesc &readBuf, + std::shared_ptr procBuf, + std::vector &captureConvBuffer, + std::vector &rendererConvBuffer + ) : readBuf_(readBuf), + procBuf_(std::move(procBuf)), + captureConvBuffer_(captureConvBuffer), + rendererConvBuffer_(rendererConvBuffer) + { + } + + bool isConvertReadFormat_ = false; + uint32_t dstSpanSizeInframe_ = 0; + AudioSamplingRate srcSamplingRate = SAMPLE_RATE_48000; + + const BufferDesc &readBuf_; + std::shared_ptr procBuf_; + std::vector &captureConvBuffer_; + std::vector &rendererConvBuffer_; +}; + class IAudioProcessStream { public: /** @@ -75,6 +99,11 @@ public: virtual StreamStatus GetStreamStatus() {return STREAM_IDEL;} virtual int32_t SetAudioHapticsSyncId(int32_t audioHapticsSyncId) = 0; virtual int32_t GetAudioHapticsSyncId() = 0; + + virtual int32_t WriteToSpecialProcBuf(AudioCaptureDataProcParams &procParams) + { + return SUCCESS; + } }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/common/src/format_converter.cpp b/services/audio_service/common/src/format_converter.cpp index 9e4edce927..f26fe83edc 100644 --- a/services/audio_service/common/src/format_converter.cpp +++ b/services/audio_service/common/src/format_converter.cpp @@ -272,6 +272,52 @@ int32_t FormatConverter::F32StereoToS32Stereo(const BufferDesc &srcDesc, const B return 0; } +int32_t FormatConverter::F32StereoToF32Mono(const BufferDesc &srcDesc, const BufferDesc &dstDesc) +{ + const size_t half = 2; // stereo has 2 channels + if (srcDesc.bufLength == 0 || dstDesc.bufLength == 0 || + srcDesc.bufLength != dstDesc.bufLength / half || + srcDesc.buffer == nullptr || dstDesc.buffer == nullptr) { + return -1; + } + + float *srcPtr = reinterpret_cast(srcDesc.buffer); + float *dstPtr = reinterpret_cast(dstDesc.buffer); + size_t count = srcDesc.bufLength / (sizeof(float) * half); + + for (size_t idx = 0; idx < count; idx++) { + float left = *srcPtr++; + float right = *srcPtr++; + *dstPtr++ = (left + right) / 2.0f; // 2.0f is average to mono + } + return 0; +} + +int32_t FormatConverter::F32StereoToS16Mono(const BufferDesc &srcDesc, const BufferDesc &dstDesc) +{ + const size_t half = 2; // stereo has 2 channels + const size_t outSampleSize = sizeof(int16_t); + if (srcDesc.bufLength == 0 || dstDesc.bufLength == 0 || + (srcDesc.bufLength / (half * sizeof(float)) * outSampleSize) != dstDesc.bufLength || + srcDesc.buffer == nullptr || dstDesc.buffer == nullptr) { + return -1; + } + + float *srcPtr = reinterpret_cast(srcDesc.buffer); + int16_t *dstPtr = reinterpret_cast(dstDesc.buffer); + size_t count = srcDesc.bufLength / (sizeof(float) * half); + + for (size_t idx = 0; idx < count; idx++) { + float left = CapMax(*srcPtr++); // apply safety clamping + float right = CapMax(*srcPtr++); + float mono = (left + right) / 2.0f; // 2.0f is average to mono + + // convert to 16 bit PCM with proper scaling + *dstPtr++ = static_cast(mono * (1 << (BIT_16 - 1))); + } + return 0; +} + int32_t FormatConverter::S16StereoToF32Stereo(const BufferDesc &srcDesc, const BufferDesc &dstDesc) { size_t half = 2; @@ -394,5 +440,64 @@ int32_t FormatConverter::S32StereoToS16Stereo(std::vector &audioBuffer, st return 0; } +FormatHandlerMap FormatConverter::formatHandlers = []() { + FormatHandlerMap handlers; + + handlers[{STEREO, SAMPLE_S16LE, STEREO, SAMPLE_S16LE}] = + [](const BufferDesc &inBuf, const BufferDesc &outBuf, bool &isDoConvert) { + isDoConvert = false; + return 0; + }; + + handlers[{STEREO, SAMPLE_S16LE, MONO, SAMPLE_S16LE}] = + [](const BufferDesc &inBuf, const BufferDesc &outBuf, bool &isDoConvert) { + isDoConvert = true; + return FormatConverter::S16StereoToS16Mono(inBuf, outBuf); + }; + + handlers[{STEREO, SAMPLE_S16LE, STEREO, SAMPLE_F32LE}] = + [](const BufferDesc &inBuf, const BufferDesc &outBuf, bool &isDoConvert) { + isDoConvert = true; + return FormatConverter::S16StereoToF32Stereo(inBuf, outBuf); + }; + + handlers[{STEREO, SAMPLE_S16LE, MONO, SAMPLE_F32LE}] = + [](const BufferDesc &inBuf, const BufferDesc &outBuf, bool &isDoConvert) { + isDoConvert = true; + return FormatConverter::S16StereoToF32Mono(inBuf, outBuf); + }; + + handlers[{STEREO, SAMPLE_F32LE, STEREO, SAMPLE_F32LE}] = + [](const BufferDesc &inBuf, const BufferDesc &outBuf, bool &isDoConvert) { + isDoConvert = false; + return 0; + }; + + handlers[{STEREO, SAMPLE_F32LE, MONO, SAMPLE_F32LE}] = + [](const BufferDesc &inBuf, const BufferDesc &outBuf, bool &isDoConvert) { + isDoConvert = true; + return FormatConverter::F32StereoToF32Mono(inBuf, outBuf); + }; + + handlers[{STEREO, SAMPLE_F32LE, STEREO, SAMPLE_S16LE}] = + [](const BufferDesc &inBuf, const BufferDesc &outBuf, bool &isDoConvert) { + isDoConvert = true; + return FormatConverter::F32StereoToS16Stereo(inBuf, outBuf); + }; + + handlers[{STEREO, SAMPLE_F32LE, MONO, SAMPLE_S16LE}] = + [](const BufferDesc &inBuf, const BufferDesc &outBuf, bool &isDoConvert) { + isDoConvert = true; + return FormatConverter::F32StereoToS16Mono(inBuf, outBuf); + }; + + return handlers; +}(); + +FormatHandlerMap &FormatConverter::GetFormatHandlers() +{ + return formatHandlers; +} + } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/include/audio_endpoint.h b/services/audio_service/server/include/audio_endpoint.h index 9ec75f6c52..3e916b5eb0 100644 --- a/services/audio_service/server/include/audio_endpoint.h +++ b/services/audio_service/server/include/audio_endpoint.h @@ -102,6 +102,9 @@ public: virtual AudioMode GetAudioMode() const = 0; + virtual int32_t AddCaptureInjector(const uint32_t &sinkPortIndex, const SourceType &sourceType) = 0; + virtual int32_t RemoveCaptureInjector(const uint32_t &sinkPortIndex, const SourceType &sourceType) = 0; + virtual ~AudioEndpoint() = default; protected: @@ -110,7 +113,8 @@ protected: AudioDeviceDescriptor deviceInfo_ = AudioDeviceDescriptor(AudioDeviceDescriptor::DEVICE_INFO); private: - virtual bool Config(const AudioDeviceDescriptor &deviceInfo, AudioStreamInfo &streamInfo) = 0; + virtual bool Config(const AudioDeviceDescriptor &deviceInfo, AudioStreamInfo &streamInfo, + AudioStreamType streamType) = 0; }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/include/audio_endpoint_private.h b/services/audio_service/server/include/audio_endpoint_private.h index 6a653198c9..fcf2200e83 100644 --- a/services/audio_service/server/include/audio_endpoint_private.h +++ b/services/audio_service/server/include/audio_endpoint_private.h @@ -32,6 +32,8 @@ #include "source/i_audio_capture_source.h" #include "audio_ring_cache.h" #include "audio_stream_info.h" +#include "audio_injector_service.h" +#include "audio_limiter.h" namespace OHOS { namespace AudioStandard { @@ -55,10 +57,11 @@ private: class AudioEndpointInner : public AudioEndpoint { public: static constexpr int64_t INVALID_DELAY_STOP_HDI_TIME_NO_RUNNING_NS = -1; - AudioEndpointInner(EndpointType type, uint64_t id, const AudioProcessConfig &clientConfig); + AudioEndpointInner(EndpointType type, uint64_t id, AudioMode audioMode); ~AudioEndpointInner(); - bool Config(const AudioDeviceDescriptor &deviceInfo, AudioStreamInfo &streamInfo) override; + bool Config(const AudioDeviceDescriptor &deviceInfo, AudioStreamInfo &streamInfo, + AudioStreamType streamType) override; bool StartDevice(EndpointStatus preferredState = INVALID, int64_t delayStopTime_ = INVALID_DELAY_STOP_HDI_TIME_NO_RUNNING_NS); void HandleStartDeviceFailed(); @@ -122,6 +125,9 @@ public: void BindCore(); void CheckWakeUpTime(int64_t &wakeUpTime); + + int32_t AddCaptureInjector(const uint32_t &sinkPortIndex, const SourceType &sourceType) override; + int32_t RemoveCaptureInjector(const uint32_t &sinkPortIndex, const SourceType &sourceType) override; private: AudioProcessConfig GetInnerCapConfig(); void StartThread(const IAudioSinkAttr &attr); @@ -139,8 +145,6 @@ private: void HandleZeroVolumeStartEvent(); void HandleZeroVolumeStopEvent(); void HandleRendererDataParams(const AudioStreamData &srcData, const AudioStreamData &dstData, bool applyVol = true); - int32_t HandleCapturerDataParams(RingBufferWrapper &writeBuf, const BufferDesc &readBuf, - const BufferDesc &convertedBuffer); void ZeroVolumeCheck(const int32_t vol); int64_t GetPredictNextReadTime(uint64_t posInFrame); int64_t GetPredictNextWriteTime(uint64_t posInFrame); @@ -182,9 +186,8 @@ private: bool IsNearlinkAbsVolSupportStream(DeviceType deviceType, AudioVolumeType volumeType); - int32_t WriteToSpecialProcBuf(const std::shared_ptr &procBuf, const BufferDesc &readBuf, - const BufferDesc &convertedBuffer, bool muteFlag); void WriteToProcessBuffers(const BufferDesc &readBuf); + int32_t ReadFromEndpoint(uint64_t curReadPos); bool KeepWorkloopRunning(); @@ -219,7 +222,6 @@ private: int32_t CreateDupBufferInner(int32_t innerCapId); int32_t WriteDupBufferInner(const BufferDesc &bufferDesc, int32_t innerCapId); bool PrepareRingBuffer(size_t i, uint64_t curRead, RingBufferWrapper& ringBuffer); - int32_t WriteToRingBuffer(RingBufferWrapper &writeBuf, const BufferDesc &buffer); void SetupMoveCallback(size_t i, uint64_t curRead, const RingBufferWrapper& ringBuffer, std::function& moveClientIndex); void AddProcessStreamToList(IAudioProcessStream *processStream, @@ -229,11 +231,24 @@ private: bool NeedUseTempBuffer(const RingBufferWrapper &ringBuffer, size_t spanSizeInByte); void PrepareStreamDataBuffer(size_t i, size_t spanSizeInByte, RingBufferWrapper &ringBuffer, AudioStreamData &streamData); + int32_t WriteDupBufferInnerForWriteModeInner(const BufferDesc &bufferDesc, int32_t innerCapId); int32_t WriteDupBufferInnerForCallbackModeInner(const BufferDesc &bufferDesc, int32_t innerCapId); static bool IsDupRenderCallbackMode(int32_t engineFlag, bool isDualStream); static bool IsDualStream(const CaptureInfo &capInfo); + + int32_t PeekRendererInjectData(const BufferDesc &readBuf, BufferDesc &rendererOrgDesc, + AudioStreamInfo &streamInfo); + int32_t ConvertDataFormat(const BufferDesc &readBuf, BufferDesc &rendererOrgDesc, + AudioStreamInfo &streamInfo, BufferDesc &rendererConvDesc, + BufferDesc &captureConvDesc); + float* MixRendererAndCaptureData(const size_t bufLength, BufferDesc &rendererConvDesc, + BufferDesc &captureConvDesc); + int32_t CreateAndCfgLimiter(const size_t bufLength, const AudioStreamInfo &streamInfo); + int32_t LimitMixData(float *inBuff, float *outBuff, const size_t bufLength, + const AudioStreamInfo &streamInfo); + void InjectToCaptureDataProc(const BufferDesc &readBuf); private: static constexpr int64_t ONE_MILLISECOND_DURATION = 1000000; // 1ms static constexpr int64_t TWO_MILLISECOND_DURATION = 2000000; // 2ms @@ -273,11 +288,12 @@ private: EndpointType endpointType_; AdapterType adapterType_ = ADAPTER_TYPE_FAST; int32_t id_ = 0; + AudioMode audioMode_ = AUDIO_MODE_PLAYBACK; + std::mutex listLock_; std::vector processList_; std::vector> processBufferList_; std::vector> processTmpBufferList_; - AudioProcessConfig clientConfig_; std::atomic isInited_ = false; @@ -355,6 +371,17 @@ private: bool coreBinded_ = false; bool isExistLoopback_ = false; int32_t audioHapticsSyncId_ = false; + + std::mutex injectLock_; // protect isNeedInject_、injectSinkPortIdx_ + bool isNeedInject_ = false; + uint32_t injectSinkPortIdx_ = UINT32_INVALID_VALUE; + + bool isConvertReadFormat_ = false; + AudioInjectorService &injector_; + std::vector injectPeekBuffer_; // reuse for mix proc, 7.5k, need consider free + std::vector rendererConvBuffer_; // reuse for resample proc, 7.5k, need consider free + std::vector captureConvBuffer_; // reuse for limit proc, 7.5k, need consider free + std::shared_ptr limiter_ = nullptr; }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/include/audio_injector_service.h b/services/audio_service/server/include/audio_injector_service.h index 0b5dd8c84f..b2cfa2991d 100644 --- a/services/audio_service/server/include/audio_injector_service.h +++ b/services/audio_service/server/include/audio_injector_service.h @@ -30,13 +30,14 @@ public: int32_t PeekAudioData(const uint32_t sinkPortIndex, uint8_t *buffer, const size_t bufferSize, AudioStreamInfo &streamInfo); void SetSinkPortIdx(uint32_t sinkPortIdx); - int32_t GetSinkPortIdx(); + uint32_t GetSinkPortIdx(); + AudioModuleInfo &GetModuleInfo(); private: AudioInjectorService(); AudioInjectorService(const AudioInjectorService&) = delete; AudioInjectorService& operator=(const AudioInjectorService&) = delete; private: - AudioModuleInfo moudleInfo_; + AudioModuleInfo moduleInfo_; uint32_t sinkPortIndex_; }; } // namespace AudioStandard diff --git a/services/audio_service/server/include/audio_process_in_server.h b/services/audio_service/server/include/audio_process_in_server.h index 9305568ed2..7e50762764 100644 --- a/services/audio_service/server/include/audio_process_in_server.h +++ b/services/audio_service/server/include/audio_process_in_server.h @@ -27,6 +27,7 @@ #include "audio_schedule_guard.h" #include "audio_stream_monitor.h" #include "audio_stream_checker.h" +#include "audio_proresampler.h" namespace OHOS { namespace AudioStandard { @@ -145,6 +146,8 @@ public: uint32_t GetSpanSizeInFrame() override; uint32_t GetByteSizePerFrame() override; + + int32_t WriteToSpecialProcBuf(AudioCaptureDataProcParams &procParams) override; public: const AudioProcessConfig processConfig_; @@ -158,6 +161,13 @@ private: void ReportDataToResSched(std::unordered_map payload, uint32_t type); void NotifyXperfOnPlayback(AudioMode audioMode, XperfEventId eventId); + int32_t HandleCapturerDataParams(RingBufferWrapper &writeBuf, AudioCaptureDataProcParams &procParams); + void SetCaptureStreamInfo(AudioStreamInfo &srcInfo, AudioCaptureDataProcParams &procParams); + int32_t CaptureDataResampleProcess(const size_t bufLen, BufferDesc &outBuf, AudioStreamInfo &srcInfo, + AudioCaptureDataProcParams &procParams); + int32_t CapturerDataFormatAndChnConv(RingBufferWrapper &writeBuf, BufferDesc &resampleOutBuf, + const AudioStreamInfo &srcInfo, const AudioStreamInfo &dstInfo); + int32_t WriteToRingBuffer(RingBufferWrapper &writeBuf, const BufferDesc &buffer); private: std::atomic muteFlag_ = false; std::atomic silentModeAndMixWithOthers_ = false; @@ -209,6 +219,8 @@ private: std::atomic audioHapticsSyncId_ = 0; StreamStatus streamStatusInServer_ = STREAM_INVALID; + + std::unique_ptr resampler_ = nullptr; }; } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/include/audio_service.h b/services/audio_service/server/include/audio_service.h index d11ddc3a16..95d370cf9b 100644 --- a/services/audio_service/server/include/audio_service.h +++ b/services/audio_service/server/include/audio_service.h @@ -164,8 +164,9 @@ public: private: AudioService(); void DelayCallReleaseEndpoint(std::string endpointName); + bool IsSameAudioStreamInfoNotIncludeSample(AudioStreamInfo &newStreamInfo, AudioStreamInfo &oldStreamInfo); ReuseEndpointType GetReuseEndpointType(AudioDeviceDescriptor &deviceInfo, - const std::string &deviceKey, AudioStreamInfo &streamInfo); + const std::string &deviceKey, AudioStreamInfo &streamInfo, int32_t endpointFlag); void InsertRenderer(uint32_t sessionId, std::shared_ptr renderer); void InsertCapturer(uint32_t sessionId, std::shared_ptr capturer); #ifdef HAS_FEATURE_INNERCAPTURER diff --git a/services/audio_service/server/src/audio_endpoint.cpp b/services/audio_service/server/src/audio_endpoint.cpp index d904d10bc1..4e7edad2bb 100644 --- a/services/audio_service/server/src/audio_endpoint.cpp +++ b/services/audio_service/server/src/audio_endpoint.cpp @@ -38,6 +38,7 @@ #endif #include "audio_volume.h" #include "audio_stream_monitor.h" +#include "simd_utils.h" namespace OHOS { namespace AudioStandard { @@ -75,10 +76,10 @@ std::shared_ptr AudioEndpoint::CreateEndpoint(EndpointType type, const AudioProcessConfig &clientConfig, const AudioDeviceDescriptor &deviceInfo, AudioStreamInfo &streamInfo) { std::shared_ptr audioEndpoint = nullptr; - audioEndpoint = std::make_shared(type, id, clientConfig); + audioEndpoint = std::make_shared(type, id, clientConfig.audioMode); CHECK_AND_RETURN_RET_LOG(audioEndpoint != nullptr, nullptr, "Create AudioEndpoint failed."); - if (!audioEndpoint->Config(deviceInfo, streamInfo)) { + if (!audioEndpoint->Config(deviceInfo, streamInfo, clientConfig.streamType)) { AUDIO_ERR_LOG("Config AudioEndpoint failed!"); audioEndpoint = nullptr; } @@ -100,11 +101,11 @@ AudioStreamInfo &AudioEndpoint::GetAudioStreamInfo() return dstStreamInfo_; } -AudioEndpointInner::AudioEndpointInner(EndpointType type, uint64_t id, - const AudioProcessConfig &clientConfig) : endpointType_(type), id_(id), clientConfig_(clientConfig) +AudioEndpointInner::AudioEndpointInner(EndpointType type, uint64_t id, AudioMode audioMode) + : endpointType_(type), id_(id), audioMode_(audioMode), injector_(AudioInjectorService::GetInstance()) { AUDIO_INFO_LOG("AudioEndpoint type:%{public}d", endpointType_); - if (clientConfig_.audioMode == AUDIO_MODE_PLAYBACK) { + if (audioMode == AUDIO_MODE_PLAYBACK) { logUtilsTag_ = "AudioEndpoint::Play"; } else { logUtilsTag_ = "AudioEndpoint::Rec"; @@ -541,7 +542,8 @@ void AudioEndpointInner::StartThread(const IAudioSinkAttr &attr) DumpFileUtil::OpenDumpFile(DumpFileUtil::DUMP_SERVER_PARA, dumpHdiName_, &dumpHdi_); } -bool AudioEndpointInner::Config(const AudioDeviceDescriptor &deviceInfo, AudioStreamInfo &streamInfo) +bool AudioEndpointInner::Config(const AudioDeviceDescriptor &deviceInfo, AudioStreamInfo &streamInfo, + AudioStreamType streamType) { AUDIO_INFO_LOG("Role %{public}d, format %{public}d", deviceInfo.deviceRole_, streamInfo.format); @@ -579,7 +581,7 @@ bool AudioEndpointInner::Config(const AudioDeviceDescriptor &deviceInfo, AudioSt Volume vol = {true, 1.0f, 0}; DeviceType deviceType = PolicyHandler::GetInstance().GetActiveOutPutDevice(); - if ((clientConfig_.streamType == STREAM_VOICE_COMMUNICATION || clientConfig_.streamType == STREAM_VOICE_CALL) && + if ((streamType == STREAM_VOICE_COMMUNICATION || streamType == STREAM_VOICE_CALL) && endpointType_ == TYPE_VOIP_MMAP) { PolicyHandler::GetInstance().GetSharedVolume(STREAM_VOICE_CALL, deviceType, vol); sink->SetVolume(vol.volumeFloat, vol.volumeFloat); @@ -1008,7 +1010,9 @@ int32_t AudioEndpointInner::OnPause(IAudioProcessStream *processStream) if (endpointStatus_ == IDEL) { // delay call sink stop when no process running AUDIO_PRERELEASE_LOGI("OnPause status is IDEL, need delay call stop"); - delayStopTime_ = ClockTime::GetCurNano() + ((clientConfig_.audioMode == AUDIO_MODE_PLAYBACK) + CHECK_AND_RETURN_RET_LOG(processStream != nullptr, ERR_NULL_POINTER, "processStream is nullptr."); + AudioMode audioMode = processStream->GetAudioProcessConfig().audioMode; + delayStopTime_ = ClockTime::GetCurNano() + ((audioMode == AUDIO_MODE_PLAYBACK) ? PLAYBACK_DELAY_STOP_HDI_TIME_NS : RECORDER_DELAY_STOP_HDI_TIME_NS); } // todo @@ -1057,7 +1061,8 @@ int32_t AudioEndpointInner::LinkProcessStream(IAudioProcessStream *processStream if (isDeviceRunningInIdel_) { delayStopTime_ = INT64_MAX; CHECK_AND_RETURN_RET_LOG(StartDevice(), ERR_OPERATION_FAILED, "StartDevice failed"); - delayStopTime_ = ClockTime::GetCurNano() + ((clientConfig_.audioMode == AUDIO_MODE_PLAYBACK) + AudioMode audioMode = processStream->GetAudioProcessConfig().audioMode; + delayStopTime_ = ClockTime::GetCurNano() + ((audioMode == AUDIO_MODE_PLAYBACK) ? PLAYBACK_DELAY_STOP_HDI_TIME_NS : LINK_RECORDER_DELAY_STOP_HDI_TIME_NS); } } @@ -1371,15 +1376,19 @@ void AudioEndpointInner::GetAllReadyProcessData(std::vector &au AudioEndpointInner::VolumeResult AudioEndpointInner::CalculateVolume(size_t i) { Volume vol = {true, 1.0f, 0}; - AudioStreamType streamType = processList_[i]->GetAudioStreamType(); AudioVolumeType volumeType = VolumeUtils::GetVolumeTypeFromStreamType(streamType); DeviceType deviceType = PolicyHandler::GetInstance().GetActiveOutPutDevice(); bool getVolumeRet = PolicyHandler::GetInstance().GetSharedVolume(volumeType, deviceType, vol); + + AudioProcessConfig clientConfig = processList_[i]->GetAudioProcessConfig(); + bool isVirtualKeyboard = clientConfig.rendererInfo.isVirtualKeyboard; + int32_t appUid = clientConfig.appInfo.appUid; + AudioVolumeMode volumeMode = clientConfig.rendererInfo.volumeMode; + int32_t doNotDisturbStatusVolume = static_cast(AudioVolume::GetInstance()->GetDoNotDisturbStatusVolume( - streamType, clientConfig_.appInfo.appUid, processList_[i]->GetAudioSessionId())); - float appVolume = AudioVolume::GetInstance()->GetAppVolume(clientConfig_.appInfo.appUid, - clientConfig_.rendererInfo.volumeMode); + streamType, appUid, processList_[i]->GetAudioSessionId())); + float appVolume = AudioVolume::GetInstance()->GetAppVolume(appUid, volumeMode); int32_t volumeFromOhaudioBuffer = processBufferList_[i]->GetStreamVolume() * processBufferList_[i]->GetDuckFactor() * processBufferList_[i]->GetMuteFactor() * (1 << VOLUME_SHIFT_NUMBER); float baseVolume = volumeFromOhaudioBuffer * appVolume * doNotDisturbStatusVolume; @@ -1389,7 +1398,7 @@ AudioEndpointInner::VolumeResult AudioEndpointInner::CalculateVolume(size_t i) && volumeType == STREAM_MUSIC && PolicyHandler::GetInstance().IsAbsVolumeSupported()) || !getVolumeRet || IsNearlinkAbsVolSupportStream(deviceInfo_.deviceType_, volumeType)) { result.volumeStart = vol.isMute ? 0 : static_cast(baseVolume); - } else if (clientConfig_.rendererInfo.isVirtualKeyboard) { + } else if (isVirtualKeyboard) { result.volumeStart = vol.isMute ? 0 : static_cast(baseVolume); } else { result.volumeStart = vol.isMute ? 0 : static_cast(baseVolume * vol.volumeFloat); @@ -1664,7 +1673,7 @@ float AudioEndpointInner::GetMaxAmplitude() AudioMode AudioEndpointInner::GetAudioMode() const { - return clientConfig_.audioMode; + return audioMode_; } int64_t AudioEndpointInner::GetPredictNextReadTime(uint64_t posInFrame) @@ -1891,117 +1900,141 @@ bool AudioEndpointInner::KeepWorkloopRunning() return false; } -int32_t AudioEndpointInner::WriteToSpecialProcBuf(const std::shared_ptr &procBuf, - const BufferDesc &readBuf, const BufferDesc &convertedBuffer, bool muteFlag) +void AudioEndpointInner::WriteToProcessBuffers(const BufferDesc &readBuf) { - CHECK_AND_RETURN_RET_LOG(procBuf != nullptr, ERR_INVALID_HANDLE, "process buffer is null."); - uint64_t curWritePos = procBuf->GetCurWriteFrame(); - Trace trace("AudioEndpoint::WriteProcessData-<" + std::to_string(curWritePos)); + CheckRecordSignal(readBuf.buffer, readBuf.bufLength); + std::lock_guard lock(listLock_); + for (size_t i = 0; i < processBufferList_.size(); i++) { + CHECK_AND_CONTINUE_LOG(processBufferList_[i] != nullptr && + processList_[i] != nullptr, "process buffer %{public}zu is null.", i); + CHECK_AND_CONTINUE(processList_[i]->GetStreamInServerStatus() == STREAM_RUNNING); - int32_t writeAbleSize = procBuf->GetWritableDataFrames(); - if (writeAbleSize <= 0 || static_cast(writeAbleSize) <= dstSpanSizeInframe_) { - AUDIO_WARNING_LOG("client read too slow: curWritePos:%{public}" PRIu64" writeAbleSize:%{public}d", - curWritePos, writeAbleSize); - return ERR_OPERATION_FAILED; + AudioCaptureDataProcParams procParams(readBuf, processBufferList_[i], + captureConvBuffer_, rendererConvBuffer_); + procParams.isConvertReadFormat_ = isConvertReadFormat_; + procParams.dstSpanSizeInframe_ = dstSpanSizeInframe_; + procParams.srcSamplingRate = dstStreamInfo_.samplingRate; + int32_t ret = processList_[i]->WriteToSpecialProcBuf(procParams); + CHECK_AND_CONTINUE_LOG(ret == SUCCESS, + "endpoint write to process buffer %{public}zu fail, ret %{public}d.", i, ret); + AUDIO_DEBUG_LOG("endpoint process buffer %{public}zu write success.", i); } +} - RingBufferWrapper ringBuffer; - int32_t ret = procBuf->GetAllWritableBufferFromPosFrame(curWritePos, ringBuffer); - CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "get write buffer fail, ret %{public}d.", ret); +int32_t AudioEndpointInner::PeekRendererInjectData(const BufferDesc &readBuf, BufferDesc &rendererOrgDesc, + AudioStreamInfo &streamInfo) +{ + size_t bufLength = readBuf.bufLength; // unit of byte, s16le format + uint8_t *renderBuf = ReallocVectorBufferAndClear(injectPeekBuffer_, bufLength); + rendererOrgDesc.buffer = renderBuf; + rendererOrgDesc.bufLength = bufLength; + int32_t ret = injector_.PeekAudioData(injectSinkPortIdx_, renderBuf, bufLength, streamInfo); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "peek renderer data fail."); - uint32_t totalSizeInFrame; - uint32_t byteSizePerFrame; - procBuf->GetSizeParameter(totalSizeInFrame, byteSizePerFrame); - CHECK_AND_RETURN_RET_LOG(byteSizePerFrame > 0, ERR_OPERATION_FAILED, "byteSizePerFrame is 0"); - uint32_t writeableSizeInFrame = ringBuffer.dataLength / byteSizePerFrame; - if (writeableSizeInFrame > dstSpanSizeInframe_) { - ringBuffer.dataLength = dstSpanSizeInframe_ * byteSizePerFrame; - } + return SUCCESS; +} - if (muteFlag) { - ringBuffer.SetBuffersValueWithSpecifyDataLen(0); - } else { - ret = HandleCapturerDataParams(ringBuffer, readBuf, convertedBuffer); - } +int32_t AudioEndpointInner::ConvertDataFormat(const BufferDesc &readBuf, BufferDesc &rendererOrgDesc, + AudioStreamInfo &streamInfo, BufferDesc &rendererConvDesc, + BufferDesc &captureConvDesc) +{ + CHECK_AND_RETURN_RET_LOG(streamInfo.channels == STEREO && streamInfo.channels == dstStreamInfo_.channels, + ERROR, "now only support STEREO, renderer chn:%{public}d, capture chn:%{public}d", + streamInfo.channels, dstStreamInfo_.channels); + CHECK_AND_RETURN_RET_LOG(streamInfo.format == SAMPLE_S16LE && streamInfo.format == dstStreamInfo_.format, + ERROR, "now only support s16le, renderer format:%{public}d, capture format:%{public}d", + streamInfo.format, dstStreamInfo_.format); + CHECK_AND_RETURN_RET_LOG(streamInfo.samplingRate == dstStreamInfo_.samplingRate, + ERROR, "now only support s16le, renderer rate:%{public}d, capture rate:%{public}d", + streamInfo.samplingRate, dstStreamInfo_.samplingRate); - CHECK_AND_RETURN_RET_LOG(ret == EOK, ERR_WRITE_FAILED, "memcpy data to process buffer fail, " - "curWritePos %{public}" PRIu64", ret %{public}d.", curWritePos, ret); + size_t floatBufLen = readBuf.bufLength * 2; // int16_t to float, need 2 muti buff len, unit of byte + rendererConvDesc = {ReallocVectorBufferAndClear(rendererConvBuffer_, floatBufLen), floatBufLen}; + int32_t ret = FormatConverter::S16StereoToF32Stereo(rendererOrgDesc, rendererConvDesc); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "convert renderer data fail."); + + captureConvDesc = {ReallocVectorBufferAndClear(captureConvBuffer_, floatBufLen), floatBufLen}; + ret = FormatConverter::S16StereoToF32Stereo(readBuf, captureConvDesc); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "convert capture data fail."); - procBuf->SetHandleInfo(curWritePos, ClockTime::GetCurNano()); - ret = procBuf->SetCurWriteFrame(curWritePos + dstSpanSizeInframe_); - if (ret != SUCCESS) { - AUDIO_WARNING_LOG("set procBuf next write frame fail, ret %{public}d.", ret); - return ERR_OPERATION_FAILED; - } return SUCCESS; } -int32_t AudioEndpointInner::WriteToRingBuffer(RingBufferWrapper &writeBuf, const BufferDesc &buffer) +float* AudioEndpointInner::MixRendererAndCaptureData(const size_t bufLength, BufferDesc &rendererConvDesc, + BufferDesc &captureConvDesc) { - CHECK_AND_RETURN_RET_LOG(buffer.buffer != nullptr && buffer.bufLength > 0, ERR_WRITE_FAILED, "failed"); - return writeBuf.CopyInputBufferValueToCurBuffer(RingBufferWrapper{ - .basicBufferDescs = {{ - {.buffer = buffer.buffer, .bufLength = buffer.bufLength}, - {.buffer = nullptr, .bufLength = 0}}}, - .dataLength = buffer.bufLength - }); + size_t mixFloatLen = bufLength / sizeof(float); // unit of float + float *leftBuff = reinterpret_cast(rendererConvDesc.buffer); + float *rightBuff = reinterpret_cast(captureConvDesc.buffer); + float *mixBuff = reinterpret_cast(ReallocVectorBufferAndClear(injectPeekBuffer_, bufLength)); // reuse buf + HPAE::SimdPointByPointAdd(mixFloatLen, leftBuff, rightBuff, mixBuff); + + return mixBuff; } -int32_t AudioEndpointInner::HandleCapturerDataParams(RingBufferWrapper &writeBuf, const BufferDesc &readBuf, - const BufferDesc &convertedBuffer) +int32_t AudioEndpointInner::CreateAndCfgLimiter(const size_t bufLength, const AudioStreamInfo &streamInfo) { - if (clientConfig_.streamInfo.format == SAMPLE_S16LE && clientConfig_.streamInfo.channels == STEREO) { - return WriteToRingBuffer(writeBuf, readBuf); - } - if (clientConfig_.streamInfo.format == SAMPLE_S16LE && clientConfig_.streamInfo.channels == MONO) { - int32_t ret = FormatConverter::S16StereoToS16Mono(readBuf, convertedBuffer); - CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "Convert channel from stereo to mono failed"); - ret = WriteToRingBuffer(writeBuf, convertedBuffer); - CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "memcpy_s failed"); - ret = memset_s(static_cast(convertedBuffer.buffer), convertedBuffer.bufLength, 0, - convertedBuffer.bufLength); - CHECK_AND_RETURN_RET_LOG(ret == EOK, ERR_WRITE_FAILED, "memset converted buffer to 0 failed"); - return EOK; - } - if (clientConfig_.streamInfo.format == SAMPLE_F32LE) { - int32_t ret = 0; - if (clientConfig_.streamInfo.channels == STEREO) { - ret = FormatConverter::S16StereoToF32Stereo(readBuf, convertedBuffer); - CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, - "Convert channel from s16 stereo to f32 stereo failed"); - } else if (clientConfig_.streamInfo.channels == MONO) { - ret = FormatConverter::S16StereoToF32Mono(readBuf, convertedBuffer); - CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, - "Convert channel from s16 stereo to f32 mono failed"); - } else { - return ERR_NOT_SUPPORTED; - } - ret = WriteToRingBuffer(writeBuf, convertedBuffer); - CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "memcpy_s failed"); - ret = memset_s(static_cast(convertedBuffer.buffer), convertedBuffer.bufLength, 0, - convertedBuffer.bufLength); - CHECK_AND_RETURN_RET_LOG(ret == EOK, ERR_WRITE_FAILED, "memset converted buffer to 0 failed"); - return EOK; + if (limiter_ != nullptr) { + return SUCCESS; } - return ERR_NOT_SUPPORTED; + /* create limiter */ + limiter_ = std::make_shared(fastCaptureId_); + CHECK_AND_RETURN_RET_LOG(limiter_ != nullptr, ERROR, "limiter make fail."); + + /* config limiter */ + int32_t ret = limiter_->SetConfig(bufLength, sizeof(float), streamInfo.samplingRate, streamInfo.channels); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "limiter config fail."); + + return SUCCESS; } -void AudioEndpointInner::WriteToProcessBuffers(const BufferDesc &readBuf) +int32_t AudioEndpointInner::LimitMixData(float *inBuff, float *outBuff, const size_t bufLength, + const AudioStreamInfo &streamInfo) { - CheckRecordSignal(readBuf.buffer, readBuf.bufLength); - std::lock_guard lock(listLock_); - for (size_t i = 0; i < processBufferList_.size(); i++) { - CHECK_AND_CONTINUE_LOG(processBufferList_[i] != nullptr && - processList_[i] != nullptr, "process buffer %{public}zu is null.", i); - CHECK_AND_CONTINUE(processList_[i]->GetStreamInServerStatus() == STREAM_RUNNING); + int32_t ret = CreateAndCfgLimiter(bufLength, streamInfo); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "create limiter fail."); - int32_t ret = WriteToSpecialProcBuf(processBufferList_[i], readBuf, processList_[i]->GetConvertedBuffer(), - processList_[i]->GetMuteState()); - CHECK_AND_CONTINUE_LOG(ret == SUCCESS, - "endpoint write to process buffer %{public}zu fail, ret %{public}d.", i, ret); - AUDIO_DEBUG_LOG("endpoint process buffer %{public}zu write success.", i); - } + /* proc limit */ + int32_t frameLen = bufLength / sizeof(float); + ret = limiter_->Process(frameLen, inBuff, outBuff); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "limiter process fail."); + + return SUCCESS; +} + +void AudioEndpointInner::InjectToCaptureDataProc(const BufferDesc &readBuf) +{ + /* pre proc */ + CHECK_AND_RETURN(IsInjectEnable()); + isConvertReadFormat_ = false; + CHECK_AND_RETURN(isNeedInject_ == true); + CHECK_AND_RETURN_LOG(endpointType_ == TYPE_VOIP_MMAP, "type error, cur only support voip inject."); + + /* peek renderer data */ + AudioStreamInfo streamInfo = {}; + BufferDesc rendererOrgDesc = {}; + int32_t ret = PeekRendererInjectData(readBuf, rendererOrgDesc, streamInfo); + CHECK_AND_RETURN_LOG(ret == SUCCESS, "peek renderer data fail."); + + /* convert format */ + BufferDesc rendererConvDesc = {}; + BufferDesc captureConvDesc = {}; + ret = ConvertDataFormat(readBuf, rendererOrgDesc, streamInfo, rendererConvDesc, captureConvDesc); + CHECK_AND_RETURN_LOG(ret == SUCCESS, "convert format data fail."); + + /* mix */ + size_t floatBufLength = readBuf.bufLength * 2; // unit of byte, 2 is int16_t to float + float *mixBuff = MixRendererAndCaptureData(floatBufLength, rendererConvDesc, captureConvDesc); + + /* limit */ + float *outBuff = reinterpret_cast(ReallocVectorBufferAndClear(captureConvBuffer_, + floatBufLength)); // reuse buffer + ret = LimitMixData(mixBuff, outBuff, floatBufLength, streamInfo); + CHECK_AND_RETURN_LOG(ret == SUCCESS, "limiter fail."); + + /* post proc */ + isConvertReadFormat_ = true; } int32_t AudioEndpointInner::ReadFromEndpoint(uint64_t curReadPos) @@ -2024,6 +2057,10 @@ int32_t AudioEndpointInner::ReadFromEndpoint(uint64_t curReadPos) AudioCacheMgr::GetInstance().CacheData(dumpHdiName_, static_cast(readBuf.buffer), readBuf.bufLength); } + + /* inject renderer data to capture data, here only support voip */ + InjectToCaptureDataProc(readBuf); + WriteToProcessBuffers(readBuf); ret = memset_s(readBuf.buffer, readBuf.bufLength, 0, readBuf.bufLength); if (ret != EOK) { @@ -2394,5 +2431,44 @@ int32_t AudioEndpointInner::WriteDupBufferInner(const BufferDesc &bufferDesc, in return isCallbackMode ? WriteDupBufferInnerForCallbackModeInner(bufferDesc, innerCapId) : WriteDupBufferInnerForWriteModeInner(bufferDesc, innerCapId); } + +int32_t AudioEndpointInner::AddCaptureInjector(const uint32_t &sinkPortIndex, const SourceType &sourceType) +{ + CHECK_AND_RETURN_RET_LOG(sourceType == SOURCE_TYPE_VOICE_COMMUNICATION, ERROR, + "sourceType not voip, sourceType:%{public}u", sourceType); + + uint32_t injectSinkPortIndex = injector_.GetSinkPortIdx(); + CHECK_AND_RETURN_RET_LOG(sinkPortIndex == injectSinkPortIndex, ERROR, + "sinkPortIndex not match, inputIdx:%{public}u, objIdx:%{public}u", + sinkPortIndex, injectSinkPortIndex); + + /* need update basic info for renderer output expect data */ + AudioModuleInfo moduleInfo = injector_.GetModuleInfo(); + moduleInfo.rate = ConvertToStringForSampleRate(dstStreamInfo_.samplingRate); + moduleInfo.format = ConvertToStringForFormat(dstStreamInfo_.format); + moduleInfo.channels = ConvertToStringForChannel(dstStreamInfo_.channels); + injector_.UpdateAudioInfo(moduleInfo); + + std::lock_guard lock(injectLock_); + isNeedInject_ = true; + injectSinkPortIdx_ = sinkPortIndex; + + return SUCCESS; +} + +int32_t AudioEndpointInner::RemoveCaptureInjector(const uint32_t &sinkPortIndex, const SourceType &sourceType) +{ + CHECK_AND_RETURN_RET_LOG(sourceType == SOURCE_TYPE_VOICE_COMMUNICATION, ERROR, + "sourceType not voip, sourceType:%{public}u", sourceType); + + std::lock_guard lock(injectLock_); + CHECK_AND_RETURN_RET_LOG(sinkPortIndex == injectSinkPortIdx_, ERROR, + "sinkPortIndex not match, inputIdx:%{public}u, objIdx:%{public}u", + sinkPortIndex, injectSinkPortIdx_); + injectSinkPortIdx_ = UINT32_INVALID_VALUE; + isNeedInject_ = false; + + return SUCCESS; +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/src/audio_endpoint_performance.cpp b/services/audio_service/server/src/audio_endpoint_performance.cpp index 2285b786bb..33fdc1eab2 100644 --- a/services/audio_service/server/src/audio_endpoint_performance.cpp +++ b/services/audio_service/server/src/audio_endpoint_performance.cpp @@ -188,7 +188,8 @@ void AudioEndpointInner::CheckStandBy() if (endpointStatus_ == IDEL) { // delay call sink stop when no process running AUDIO_INFO_LOG("status is IDEL, need delay call stop"); - delayStopTime_ = ClockTime::GetCurNano() + ((clientConfig_.audioMode == AUDIO_MODE_PLAYBACK) + AudioMode audioMode = GetAudioMode(); + delayStopTime_ = ClockTime::GetCurNano() + ((audioMode == AUDIO_MODE_PLAYBACK) ? PLAYBACK_DELAY_STOP_HDI_TIME_NS : RECORDER_DELAY_STOP_HDI_TIME_NS); } } diff --git a/services/audio_service/server/src/audio_injector_service.cpp b/services/audio_service/server/src/audio_injector_service.cpp index a106310563..2cfc295892 100644 --- a/services/audio_service/server/src/audio_injector_service.cpp +++ b/services/audio_service/server/src/audio_injector_service.cpp @@ -36,9 +36,14 @@ void AudioInjectorService::SetSinkPortIdx(uint32_t sinkPortIdx) sinkPortIndex_ = sinkPortIdx; } -int32_t AudioInjectorService::GetSinkPortIdx() +uint32_t AudioInjectorService::GetSinkPortIdx() { return sinkPortIndex_; } + +AudioModuleInfo &AudioInjectorService::GetModuleInfo() +{ + return moduleInfo_; +} } // namespace AudioStandard } // namespace OHOS \ No newline at end of file diff --git a/services/audio_service/server/src/audio_process_in_server.cpp b/services/audio_service/server/src/audio_process_in_server.cpp index 04feae099f..6e2afc42f2 100644 --- a/services/audio_service/server/src/audio_process_in_server.cpp +++ b/services/audio_service/server/src/audio_process_in_server.cpp @@ -32,6 +32,7 @@ #include "audio_performance_monitor.h" #include "core_service_handler.h" #include "stream_dfx_manager.h" +#include "format_converter.h" #ifdef RESSCHE_ENABLE #include "res_type.h" #include "res_sched_client.h" @@ -900,5 +901,165 @@ StreamStatus AudioProcessInServer::GetStreamInServerStatus() { return streamStatusInServer_; } + +int32_t AudioProcessInServer::WriteToRingBuffer(RingBufferWrapper &writeBuf, const BufferDesc &buffer) +{ + CHECK_AND_RETURN_RET_LOG(buffer.buffer != nullptr && buffer.bufLength > 0, ERR_WRITE_FAILED, "failed"); + return writeBuf.CopyInputBufferValueToCurBuffer(RingBufferWrapper{ + .basicBufferDescs = {{ + {.buffer = buffer.buffer, .bufLength = buffer.bufLength}, + {.buffer = nullptr, .bufLength = 0}}}, + .dataLength = buffer.bufLength + }); +} + +void AudioProcessInServer::SetCaptureStreamInfo(AudioStreamInfo &srcInfo, AudioCaptureDataProcParams &procParams) +{ + srcInfo.channels = STEREO; + srcInfo.format = procParams.isConvertReadFormat_ ? SAMPLE_F32LE : SAMPLE_S16LE; + srcInfo.samplingRate = procParams.srcSamplingRate; +} + +int32_t AudioProcessInServer::CaptureDataResampleProcess(const size_t bufLen, + BufferDesc &outBuf, + AudioStreamInfo &srcInfo, + AudioCaptureDataProcParams &procParams) +{ + uint32_t srcRate = static_cast(srcInfo.samplingRate); + uint32_t dstRate = static_cast(processConfig_.streamInfo.samplingRate); + + /* no need resample */ + if (srcRate == dstRate) { + /* if already convert, data is not readbuf, need update to new buff */ + if (procParams.isConvertReadFormat_) { + outBuf.buffer = procParams.captureConvBuffer_.data(); + outBuf.bufLength = bufLen; + } + return SUCCESS; + } + + AUDIO_INFO_LOG("Audio capture resample, srcRate:%{public}u, dstRate:%{public}u", srcRate, dstRate); + int32_t ret; + float *resampleInBuff = nullptr; + if (srcInfo.format != SAMPLE_F32LE) { + BufferDesc convBufTmp = {ReallocVectorBufferAndClear(procParams.captureConvBuffer_, bufLen), bufLen}; + ret = FormatConverter::S16StereoToF32Stereo(outBuf, convBufTmp); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Convert s16 stereo to f32 stereo failed"); + srcInfo.format = SAMPLE_F32LE; + resampleInBuff = reinterpret_cast(convBufTmp.buffer); + } else { + resampleInBuff = reinterpret_cast(procParams.captureConvBuffer_.data()); + } + + if (resampler_ == nullptr) { + resampler_ = std::make_unique(srcRate, dstRate, srcInfo.channels, 1); + } + uint32_t resampleBuffSize = bufLen / srcInfo.channels; // resampler inner will multiply channels + float *resampleOutBuff = + reinterpret_cast(ReallocVectorBufferAndClear(procParams.rendererConvBuffer_, bufLen)); + ret = resampler_->Process(resampleInBuff, resampleBuffSize, resampleOutBuff, resampleBuffSize); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "Capture data resample failed"); + + outBuf.buffer = reinterpret_cast(resampleOutBuff); + outBuf.bufLength = bufLen; + + return SUCCESS; +} + +int32_t AudioProcessInServer::CapturerDataFormatAndChnConv(RingBufferWrapper &writeBuf, + BufferDesc &resampleOutBuf, + const AudioStreamInfo &srcInfo, + const AudioStreamInfo &dstInfo) +{ + AudioChannel srcChn = srcInfo.channels; + AudioChannel dstChn = dstInfo.channels; + AudioSampleFormat srcFormat = srcInfo.format; + AudioSampleFormat dstFormat = dstInfo.format; + FormatKey key{srcChn, srcFormat, dstChn, dstFormat}; + FormatHandlerMap formatHanlders = FormatConverter::GetFormatHandlers(); + + auto it = formatHanlders.find(key); + if (it != formatHanlders.end()) { + bool isDoConvert = false; + int32_t ret = it->second(resampleOutBuf, convertedBuffer_, isDoConvert); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "Convert format failed"); + + if (isDoConvert) { + ret = WriteToRingBuffer(writeBuf, convertedBuffer_); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "write to client buffer failed"); + ret = memset_s(static_cast(convertedBuffer_.buffer), convertedBuffer_.bufLength, 0, + convertedBuffer_.bufLength); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "memset converted buffer to 0 failed"); + return SUCCESS; + } else { + return WriteToRingBuffer(writeBuf, resampleOutBuf); + } + } + + return ERR_NOT_SUPPORTED; +} + +int32_t AudioProcessInServer::HandleCapturerDataParams(RingBufferWrapper &writeBuf, + AudioCaptureDataProcParams &procParams) +{ + AudioStreamInfo srcInfo = {}; + SetCaptureStreamInfo(srcInfo, procParams); + + size_t bufLen = procParams.readBuf_.bufLength * 2; // unit of byte, 2 is int16_t to float + BufferDesc resampleOutBuf = procParams.readBuf_; + int32_t ret = CaptureDataResampleProcess(bufLen, resampleOutBuf, srcInfo, procParams); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ERR_WRITE_FAILED, "capture data resample failed"); + + ret = CapturerDataFormatAndChnConv(writeBuf, resampleOutBuf, srcInfo, processConfig_.streamInfo); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "capture data convert failed"); + + return SUCCESS; +} + +int32_t AudioProcessInServer::WriteToSpecialProcBuf(AudioCaptureDataProcParams &procParams) +{ + std::shared_ptr procBuf = procParams.procBuf_; + CHECK_AND_RETURN_RET_LOG(procBuf != nullptr, ERR_INVALID_HANDLE, "process buffer is null."); + uint64_t curWritePos = procBuf->GetCurWriteFrame(); + Trace trace("WriteProcessData-<" + std::to_string(curWritePos)); + + int32_t writeAbleSize = procBuf->GetWritableDataFrames(); + uint32_t dstSpanSizeInframe = procParams.dstSpanSizeInframe_; + if (writeAbleSize <= 0 || static_cast(writeAbleSize) <= dstSpanSizeInframe) { + AUDIO_WARNING_LOG("client read too slow: curWritePos:%{public}" PRIu64" writeAbleSize:%{public}d", + curWritePos, writeAbleSize); + return ERR_OPERATION_FAILED; + } + + RingBufferWrapper ringBuffer; + int32_t ret = procBuf->GetAllWritableBufferFromPosFrame(curWritePos, ringBuffer); + CHECK_AND_RETURN_RET_LOG(ret == SUCCESS, ret, "get write buffer fail, ret %{public}d.", ret); + + uint32_t totalSizeInFrame; + uint32_t byteSizePerFrame; + procBuf->GetSizeParameter(totalSizeInFrame, byteSizePerFrame); + CHECK_AND_RETURN_RET_LOG(byteSizePerFrame > 0, ERR_OPERATION_FAILED, "byteSizePerFrame is 0"); + uint32_t writeableSizeInFrame = ringBuffer.dataLength / byteSizePerFrame; + if (writeableSizeInFrame > dstSpanSizeInframe) { + ringBuffer.dataLength = dstSpanSizeInframe * byteSizePerFrame; + } + + if (GetMuteState()) { + ringBuffer.SetBuffersValueWithSpecifyDataLen(0); + } else { + ret = HandleCapturerDataParams(ringBuffer, procParams); + } + + CHECK_AND_RETURN_RET_LOG(ret == EOK, ERR_WRITE_FAILED, "memcpy data to process buffer fail, " + "curWritePos %{public}" PRIu64", ret %{public}d.", curWritePos, ret); + + procBuf->SetHandleInfo(curWritePos, ClockTime::GetCurNano()); + ret = procBuf->SetCurWriteFrame(curWritePos + dstSpanSizeInframe); + if (ret != SUCCESS) { + AUDIO_WARNING_LOG("set procBuf next write frame fail, ret %{public}d.", ret); + return ERR_OPERATION_FAILED; + } + return SUCCESS; +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/server/src/audio_service.cpp b/services/audio_service/server/src/audio_service.cpp index 386cc20d3c..9f233ec20c 100644 --- a/services/audio_service/server/src/audio_service.cpp +++ b/services/audio_service/server/src/audio_service.cpp @@ -1248,14 +1248,35 @@ void AudioService::CheckBeforeRecordEndpointCreate(bool isRecord) } } +bool AudioService::IsSameAudioStreamInfoNotIncludeSample(AudioStreamInfo &newStreamInfo, + AudioStreamInfo &oldStreamInfo) +{ + return newStreamInfo.encoding == oldStreamInfo.encoding && + newStreamInfo.format == oldStreamInfo.format && + newStreamInfo.channels == oldStreamInfo.channels && + newStreamInfo.channelLayout == oldStreamInfo.channelLayout; +} + // must be called with processListMutex_ lock hold ReuseEndpointType AudioService::GetReuseEndpointType(AudioDeviceDescriptor &deviceInfo, - const std::string &deviceKey, AudioStreamInfo &streamInfo) + const std::string &deviceKey, AudioStreamInfo &streamInfo, int32_t endpointFlag) { if (endpointList_.find(deviceKey) == endpointList_.end()) { return ReuseEndpointType::CREATE_ENDPOINT; } - bool reuse = streamInfo == endpointList_[deviceKey]->GetAudioStreamInfo(); + + bool reuse = false; + AudioStreamInfo oldStreamInfo = endpointList_[deviceKey]->GetAudioStreamInfo(); + if (IsInjectEnable() && endpointList_[deviceKey]->GetDeviceRole() == INPUT_DEVICE && + endpointFlag == AUDIO_FLAG_VOIP_FAST) { + /* capture voip fast support resample, so can reuse at not same sample */ + if (IsSameAudioStreamInfoNotIncludeSample(streamInfo, oldStreamInfo)) { + reuse = true; + } + } else { + reuse = streamInfo == oldStreamInfo; + } + return reuse ? ReuseEndpointType::REUSE_ENDPOINT : ReuseEndpointType::RECREATE_ENDPOINT; } @@ -1265,7 +1286,7 @@ std::shared_ptr AudioService::GetAudioEndpointForDevice(AudioDevi // Create shared stream. int32_t endpointFlag = isVoipStream ? AUDIO_FLAG_VOIP_FAST : AUDIO_FLAG_MMAP; std::string deviceKey = AudioEndpoint::GenerateEndpointKey(deviceInfo, endpointFlag); - ReuseEndpointType type = GetReuseEndpointType(deviceInfo, deviceKey, streamInfo); + ReuseEndpointType type = GetReuseEndpointType(deviceInfo, deviceKey, streamInfo, endpointFlag); std::shared_ptr endpoint = nullptr; switch (type) { diff --git a/services/audio_service/test/unittest/BUILD.gn b/services/audio_service/test/unittest/BUILD.gn index 44d667f0e7..42dd9da35f 100644 --- a/services/audio_service/test/unittest/BUILD.gn +++ b/services/audio_service/test/unittest/BUILD.gn @@ -52,6 +52,8 @@ ohos_unittest("audio_balance_unit_test") { "../../../../frameworks/native/audioclock/include", "../../../../services/audio_policy/server/include", "../../../../services/audio_engine/manager/include", + "../../../../services/audio_engine/plugin/resample/include", + "../../../../services/audio_service/common/include/limiter", ] sources = [ "audio_group_manager_unit_test.cpp", @@ -322,6 +324,7 @@ ohos_unittest("audio_service_unit_test") { "../../../../frameworks/native/audioclock/include", "../../../../services/audio_policy/server/include", "../../../../services/audio_engine/manager/include", + "../../../../services/audio_engine/plugin/resample/include", ] sources = [ @@ -604,6 +607,7 @@ ohos_unittest("audio_process_in_server_unit_test") { "../../../../services/audio_service/common/include", "../../../../services/audio_service/common/include/dfx", "../../../../services/audio_engine/manager/include", + "../../../../services/audio_engine/plugin/resample/include", ] sources = [ "audio_process_in_server_unit_test.cpp" ] @@ -1078,6 +1082,7 @@ ohos_unittest("capturer_in_server_unit_test") { "../../../../services/audio_service/server/src/audio_workgroup_callback.cpp", "../../../../services/audio_service/server/src/audio_workgroup.cpp", "../../../../services/audio_service/server/src/audio_resource_service.cpp", + "../../../../services/audio_service/server/src/audio_injector_service.cpp", "capturer_in_server_second_unit_test.cpp", ] @@ -1098,6 +1103,7 @@ ohos_unittest("capturer_in_server_unit_test") { "../../../../frameworks/native/hdiadapter_new:hdiadapter_new", "../../../../services/audio_engine:audio_engine_manager", "../../../../services/audio_engine:audio_engine_plugins", + "../../../../services/audio_engine:audio_engine_utils", "../../../../services/audio_policy:audio_policy_client", "../../../../services/audio_policy:audio_policy_service", "../../../../services/audio_service:audio_client", diff --git a/services/audio_service/test/unittest/audio_endpoint_unit_test/include/audio_endpoint_unit_test.h b/services/audio_service/test/unittest/audio_endpoint_unit_test/include/audio_endpoint_unit_test.h index 18fdd83d24..994e8b23a9 100644 --- a/services/audio_service/test/unittest/audio_endpoint_unit_test/include/audio_endpoint_unit_test.h +++ b/services/audio_service/test/unittest/audio_endpoint_unit_test/include/audio_endpoint_unit_test.h @@ -31,6 +31,7 @@ public: // TearDown: Called after each test cases void TearDown(void); }; + } // namespace AudioStandard } // namespace OHOS #endif // AUDIO_ENDPOINT_UNIT_TEST_H \ No newline at end of file diff --git a/services/audio_service/test/unittest/audio_endpoint_unit_test/src/audio_endpoint_plus_unit_test.cpp b/services/audio_service/test/unittest/audio_endpoint_unit_test/src/audio_endpoint_plus_unit_test.cpp index e53daa6fc7..6151e979e3 100644 --- a/services/audio_service/test/unittest/audio_endpoint_unit_test/src/audio_endpoint_plus_unit_test.cpp +++ b/services/audio_service/test/unittest/audio_endpoint_unit_test/src/audio_endpoint_plus_unit_test.cpp @@ -156,7 +156,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_001, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -176,7 +176,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_002, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -196,7 +196,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_003, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -218,7 +218,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_004, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -261,7 +261,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_005, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -293,7 +293,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_006, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -317,7 +317,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_007, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -342,7 +342,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_008, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -367,7 +367,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_009, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -392,7 +392,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_010, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -419,7 +419,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_011, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -448,7 +448,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_012, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -477,7 +477,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_013, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -500,7 +500,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_014, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -525,7 +525,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_015, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -550,7 +550,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_016, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -575,7 +575,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_017, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -613,7 +613,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_018, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -636,7 +636,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_019, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -657,7 +657,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_020, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -678,7 +678,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_021, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -703,7 +703,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_022, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -727,7 +727,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_023, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -750,7 +750,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_024, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -772,7 +772,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_025, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -800,7 +800,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_026, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -830,7 +830,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_027, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -849,122 +849,6 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_027, TestSize.Level1) audioEndpointInner->CheckPlaySignal(&buffer, bufferSize); } -/* - * @tc.name : Test AudioEndpointInner API - * @tc.type : FUNC - * @tc.number: AudioEndpointInner_028 - * @tc.desc : Test AudioEndpointInner::HandleCapturerDataParams() - */ -HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_028, TestSize.Level1) -{ - AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; - uint64_t id = 123; - int32_t ret = 0; - AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); - - ASSERT_NE(audioEndpointInner, nullptr); - - RingBufferWrapper writeBuf; - BufferDesc readBuf; - BufferDesc convertedBuffer; - audioEndpointInner->clientConfig_.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE; - audioEndpointInner->clientConfig_.streamInfo.channels = AudioChannel::STEREO; - - ret = audioEndpointInner->HandleCapturerDataParams(writeBuf, readBuf, convertedBuffer); - EXPECT_EQ(ret, ERR_WRITE_FAILED); - - audioEndpointInner->clientConfig_.streamInfo.format = AudioSampleFormat::SAMPLE_F32LE; - audioEndpointInner->clientConfig_.streamInfo.channels = AudioChannel::STEREO; - - ret = audioEndpointInner->HandleCapturerDataParams(writeBuf, readBuf, convertedBuffer); - EXPECT_NE(ret, 0); - - audioEndpointInner->clientConfig_.streamInfo.format = AudioSampleFormat::SAMPLE_F32LE; - audioEndpointInner->clientConfig_.streamInfo.channels = AudioChannel::MONO; - - ret = audioEndpointInner->HandleCapturerDataParams(writeBuf, readBuf, convertedBuffer); - EXPECT_NE(ret, 0); -} - -/* - * @tc.name : Test AudioEndpointInner API - * @tc.type : FUNC - * @tc.number: AudioEndpointInner_029 - * @tc.desc : Test AudioEndpointInner::HandleCapturerDataParams() - */ -HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_029, TestSize.Level1) -{ - AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; - uint64_t id = 123; - int32_t ret = 0; - AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); - - ASSERT_NE(audioEndpointInner, nullptr); - - RingBufferWrapper writeBuf; - BufferDesc readBuf; - BufferDesc convertedBuffer; - audioEndpointInner->clientConfig_.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE; - audioEndpointInner->clientConfig_.streamInfo.channels = AudioChannel::CHANNEL_3; - - ret = audioEndpointInner->HandleCapturerDataParams(writeBuf, readBuf, convertedBuffer); - EXPECT_NE(ret, 0); -} - -/* - * @tc.name : Test AudioEndpointInner API - * @tc.type : FUNC - * @tc.number: AudioEndpointInner_030 - * @tc.desc : Test AudioEndpointInner::HandleCapturerDataParams() - */ -HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_030, TestSize.Level1) -{ - AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; - uint64_t id = 123; - int32_t ret = 0; - AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); - - ASSERT_NE(audioEndpointInner, nullptr); - - RingBufferWrapper writeBuf; - BufferDesc readBuf; - BufferDesc convertedBuffer; - audioEndpointInner->clientConfig_.streamInfo.format = AudioSampleFormat::SAMPLE_S24LE; - audioEndpointInner->clientConfig_.streamInfo.channels = AudioChannel::CHANNEL_3; - - ret = audioEndpointInner->HandleCapturerDataParams(writeBuf, readBuf, convertedBuffer); - EXPECT_NE(ret, 0); -} - -/* - * @tc.name : Test AudioEndpointInner API - * @tc.type : FUNC - * @tc.number: AudioEndpointInner_031 - * @tc.desc : Test AudioEndpointInner::HandleCapturerDataParams() - */ -HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_031, TestSize.Level1) -{ - AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; - uint64_t id = 123; - int32_t ret = 0; - AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); - - ASSERT_NE(audioEndpointInner, nullptr); - - RingBufferWrapper writeBuf; - BufferDesc readBuf; - BufferDesc convertedBuffer; - audioEndpointInner->clientConfig_.streamInfo.format = AudioSampleFormat::SAMPLE_S16LE; - audioEndpointInner->clientConfig_.streamInfo.channels = AudioChannel::STEREO; - - ret = audioEndpointInner->HandleCapturerDataParams(writeBuf, readBuf, convertedBuffer); - EXPECT_EQ(ret, ERR_WRITE_FAILED); -} - /* * @tc.name : Test AudioEndpointInner API * @tc.type : FUNC @@ -976,7 +860,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_032, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1002,7 +886,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_033, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1017,40 +901,6 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_033, TestSize.Level1) delete[] buffer; } -/* - * @tc.name : Test AudioEndpointInner API - * @tc.type : FUNC - * @tc.number: AudioEndpointInner_034 - * @tc.desc : Test AudioEndpointInner::WriteToSpecialProcBuf() - */ -HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_034, TestSize.Level1) -{ - AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; - uint64_t id = 123; - AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); - - ASSERT_NE(audioEndpointInner, nullptr); - - AudioBufferHolder bufferHolder = AudioBufferHolder::AUDIO_CLIENT; - uint32_t totalSizeInFrame = 0; - uint32_t spanSizeInFrame = 0; - uint32_t byteSizePerFrame = 0; - const std::shared_ptr procBuf = std::make_shared(bufferHolder, - totalSizeInFrame, byteSizePerFrame); - procBuf->basicBufferInfo_ = std::make_shared().get(); - - EXPECT_NE(nullptr, procBuf); - - BufferDesc readBuf2; - const BufferDesc readBuf = readBuf2; - BufferDesc convertedBuffer2; - const BufferDesc convertedBuffer = convertedBuffer2; - bool muteFlag = true; - - audioEndpointInner->WriteToSpecialProcBuf(procBuf, readBuf, convertedBuffer, muteFlag); -} - /* * @tc.name : Test AudioEndpointInner API * @tc.type : FUNC @@ -1062,7 +912,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_035, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1093,7 +943,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_036, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1116,7 +966,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_037, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1168,7 +1018,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_039, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1203,7 +1053,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_040, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1221,7 +1071,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_040, TestSize.Level1) HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_WaitAllReady_001, TestSize.Level1) { AudioProcessConfig clientConfig = {}; - auto endpoint = std::make_shared(AudioEndpoint::TYPE_MMAP, 0, clientConfig); + auto endpoint = std::make_shared(AudioEndpoint::TYPE_MMAP, 0, clientConfig.audioMode); ASSERT_NE(endpoint, nullptr); @@ -1248,7 +1098,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_WaitAllReady_001, TestSiz HWTEST_F(AudioEndpointPlusUnitTest, CheckJank_001, TestSize.Level1) { AudioProcessConfig clientConfig = {}; - auto endpoint = std::make_shared(AudioEndpoint::TYPE_MMAP, 0, clientConfig); + auto endpoint = std::make_shared(AudioEndpoint::TYPE_MMAP, 0, clientConfig.audioMode); uint32_t totalSizeInFrame = 8; uint32_t spanSizeInFrame = 2; @@ -1278,7 +1128,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_041, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); AudioBufferHolder bufferHolder = AudioBufferHolder::AUDIO_CLIENT; @@ -1310,7 +1160,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_042, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); AudioBufferHolder bufferHolder = AudioBufferHolder::AUDIO_CLIENT; @@ -1345,7 +1195,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_043, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1364,7 +1214,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_044, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1383,7 +1233,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_045, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1402,7 +1252,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_046, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1422,7 +1272,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_047, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1441,7 +1291,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_048, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1496,7 +1346,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_051, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1515,7 +1365,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_052, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1536,7 +1386,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_053, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1557,7 +1407,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_054, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1579,7 +1429,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_055, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1601,7 +1451,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_056, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1620,7 +1470,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_057, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1641,7 +1491,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_058, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1664,7 +1514,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_059, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1692,7 +1542,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_060, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1729,7 +1579,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_061, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); @@ -1763,7 +1613,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, IsInvalidBuffer_001, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); uint8_t buffer[1] = {1}; bool result = audioEndpointInner->IsInvalidBuffer(buffer, sizeof(buffer), SAMPLE_U8); EXPECT_FALSE(result); @@ -1780,7 +1630,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, IsInvalidBuffer_002, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); uint8_t buffer[1] = {0}; bool result = audioEndpointInner->IsInvalidBuffer(buffer, sizeof(buffer), SAMPLE_U8); EXPECT_TRUE(result); @@ -1797,7 +1647,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, IsInvalidBuffer_003, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); int16_t buffer[1] = {1}; bool result = audioEndpointInner->IsInvalidBuffer(reinterpret_cast(buffer), sizeof(buffer), SAMPLE_S16LE); EXPECT_FALSE(result); @@ -1814,7 +1664,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, IsInvalidBuffer_004, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); int16_t buffer[1] = {0}; bool result = audioEndpointInner->IsInvalidBuffer(reinterpret_cast(buffer), sizeof(buffer), SAMPLE_S16LE); EXPECT_TRUE(result); @@ -1831,7 +1681,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, IsInvalidBuffer_005, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointnIner = std::make_shared(type, id, clientConfig); + auto audioEndpointnIner = std::make_shared(type, id, clientConfig.audioMode); uint8_t buffer[1] = {0}; bool result = audioEndpointnIner->IsInvalidBuffer(buffer, sizeof(buffer), static_cast(-1)); EXPECT_FALSE(result); @@ -1848,7 +1698,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, CheckAudioHapticsSync_001, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointnIner = std::make_shared(type, id, clientConfig); + auto audioEndpointnIner = std::make_shared(type, id, clientConfig.audioMode); audioEndpointnIner->audioHapticsSyncId_ = 1; audioEndpointnIner->fastRenderId_ = 1; audioEndpointnIner->dstSpanSizeInframe_ = 100; @@ -1869,7 +1719,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, CheckAudioHapticsSync_002, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointnIner = std::make_shared(type, id, clientConfig); + auto audioEndpointnIner = std::make_shared(type, id, clientConfig.audioMode); audioEndpointnIner->audioHapticsSyncId_ = 1; audioEndpointnIner->fastRenderId_ = 1; audioEndpointnIner->dstSpanSizeInframe_ = 100; @@ -1892,7 +1742,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, IsNearlinkAbsVolSupportStream_001, TestSize. AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointnIner = std::make_shared(type, id, clientConfig); + auto audioEndpointnIner = std::make_shared(type, id, clientConfig.audioMode); EXPECT_TRUE(audioEndpointnIner->IsNearlinkAbsVolSupportStream(DEVICE_TYPE_NEARLINK, STREAM_MUSIC)); EXPECT_TRUE(audioEndpointnIner->IsNearlinkAbsVolSupportStream(DEVICE_TYPE_NEARLINK, STREAM_VOICE_CALL)); @@ -1909,7 +1759,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, CheckSyncInfo_001, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointnIner = std::make_shared(type, id, clientConfig); + auto audioEndpointnIner = std::make_shared(type, id, clientConfig.audioMode); audioEndpointnIner->dstSpanSizeInframe_ = 0; audioEndpointnIner->CheckSyncInfo(100); EXPECT_EQ(audioEndpointnIner->dstSpanSizeInframe_, 0); @@ -1926,7 +1776,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, ProcessToDupStream_001, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointnIner = std::make_shared(type, id, clientConfig); + auto audioEndpointnIner = std::make_shared(type, id, clientConfig.audioMode); std::vector audioDataList; AudioStreamData dstStreamData; int32_t innerCapId = 1; @@ -1946,7 +1796,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, ProcessToDupStream_001, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); CaptureInfo captureInfo; @@ -1964,7 +1814,7 @@ HWTEST_F(AudioEndpointPlusUnitTest, AudioEndpointInner_008, TestSize.Level1) AudioEndpoint::EndpointType type = AudioEndpoint::TYPE_MMAP; uint64_t id = 123; AudioProcessConfig clientConfig = {}; - auto audioEndpointInner = std::make_shared(type, id, clientConfig); + auto audioEndpointInner = std::make_shared(type, id, clientConfig.audioMode); ASSERT_NE(audioEndpointInner, nullptr); diff --git a/services/audio_service/test/unittest/audio_endpoint_unit_test/src/audio_endpoint_unit_test.cpp b/services/audio_service/test/unittest/audio_endpoint_unit_test/src/audio_endpoint_unit_test.cpp index bca0856341..67ec0d67d2 100644 --- a/services/audio_service/test/unittest/audio_endpoint_unit_test/src/audio_endpoint_unit_test.cpp +++ b/services/audio_service/test/unittest/audio_endpoint_unit_test/src/audio_endpoint_unit_test.cpp @@ -34,6 +34,39 @@ namespace AudioStandard { constexpr int32_t DEFAULT_STREAM_ID = 10; constexpr uint64_t AUDIO_ENDPOINT_ID = 123; +// Mock classes for dependencies +class MockAudioInjector : public AudioInjector { +public: + MOCK_METHOD(uint32_t, GetSinkPortIdx, (), (const, override)); + MOCK_METHOD(AudioModuleInfo, GetModuleInfo, (), (const, override)); + MOCK_METHOD(void, UpdateAudioInfo, (const AudioModuleInfo& moduleInfo), (override)); + MOCK_METHOD(int32_t, PeekAudioData, (uint32_t, uint8_t*, size_t, AudioStreamInfo&), (override)); + static std::shared_ptr GetMockInstance() + { + static auto instance = std::make_shared(); + return instance; + } +}; + +class MockFormatConverter { +public: + MOCK_METHOD(int32_t, S16StereoToF32Stereo, (const BufferDesc&, const BufferDesc&), ()); + static std::shared_ptr GetMockInstance(); +}; + +class MockHPAE { +public: + MOCK_METHOD(void, SimdPointByPointAdd, (size_t, float*, float*, float*), ()); + static std::shared_ptr GetMockInstance(); +}; + +class MockAudioLimiter : public AudioLimiter { +public: + MOCK_METHOD(int32_t, SetConfig, (size_t, size_t, AudioSamplingRate, AudioChannel), (override)); + MOCK_METHOD(int32_t, Process, (int32_t, float*, float*), (override)); + static std::shared_ptr GetMockInstance(); +}; + void AudioEndpointUnitTest::SetUpTestCase(void) { // input testsuit setup step,setup invoked before all testcases @@ -58,10 +91,10 @@ static std::shared_ptr CreateEndpointInner(AudioEndpoint::En const AudioProcessConfig &clientConfig, const AudioDeviceDescriptor &deviceInfo, AudioStreamInfo &streamInfo) { std::shared_ptr audioEndpoint = - std::make_shared(type, id, clientConfig); + std::make_shared(type, id, clientConfig.audioMode); CHECK_AND_RETURN_RET_LOG(audioEndpoint != nullptr, nullptr, "Create AudioEndpoint failed."); - if (!audioEndpoint->Config(deviceInfo, streamInfo)) { + if (!audioEndpoint->Config(deviceInfo, streamInfo, clientConfig.streamType)) { audioEndpoint = nullptr; } return audioEndpoint; @@ -75,8 +108,9 @@ static std::shared_ptr CreateInputEndpointInner(AudioEndpoin AudioStreamInfo audioStreamInfo = { SAMPLE_RATE_48000, ENCODING_PCM, SAMPLE_S16LE, STEREO, CH_LAYOUT_STEREO }; deviceInfo.networkId_ = LOCAL_NETWORK_ID; std::shared_ptr audioEndpoint = - std::make_shared(type, AUDIO_ENDPOINT_ID, config); - if (!audioEndpoint->Config(deviceInfo, audioStreamInfo)) { + std::make_shared(type, AUDIO_ENDPOINT_ID, config.audioMode); + audioEndpoint->injector_ = *MockAudioInjector::GetMockInstance(); + if (!audioEndpoint->Config(deviceInfo, audioStreamInfo, config.streamType)) { audioEndpoint = nullptr; } return audioEndpoint; @@ -526,7 +560,7 @@ HWTEST_F(AudioEndpointUnitTest, AudioEndpointMix_001, TestSize.Level1) deviceInfo.deviceRole_ = DeviceRole::INPUT_DEVICE; AudioStreamInfo audioStreamInfo = { SAMPLE_RATE_48000, ENCODING_PCM, SAMPLE_S16LE, STEREO, CH_LAYOUT_STEREO }; deviceInfo.networkId_ = LOCAL_NETWORK_ID; - result = audioEndpointInner->Config(deviceInfo, audioStreamInfo); + result = audioEndpointInner->Config(deviceInfo, audioStreamInfo, config.streamType); EXPECT_FALSE(result); processStream->SetInnerCapState(true, 1); @@ -1006,7 +1040,7 @@ HWTEST_F(AudioEndpointUnitTest, CheckStandBy_001, TestSize.Level1) { std::shared_ptr audioEndpointInner = CreateOutputEndpointInner(AudioEndpoint::TYPE_MMAP); audioEndpointInner->endpointStatus_ = AudioEndpointInner::RUNNING; - audioEndpointInner->clientConfig_.audioMode = AUDIO_MODE_PLAYBACK; + audioEndpointInner->audioMode_ = AUDIO_MODE_PLAYBACK; audioEndpointInner->CheckStandBy(); EXPECT_EQ(audioEndpointInner->endpointStatus_, AudioEndpointInner::RUNNING); } @@ -1021,7 +1055,7 @@ HWTEST_F(AudioEndpointUnitTest, CheckStandBy_002, TestSize.Level1) { std::shared_ptr audioEndpointInner = CreateOutputEndpointInner(AudioEndpoint::TYPE_MMAP); audioEndpointInner->endpointStatus_ = AudioEndpointInner::IDEL; - audioEndpointInner->clientConfig_.audioMode = AUDIO_MODE_PLAYBACK; + audioEndpointInner->audioMode_ = AUDIO_MODE_PLAYBACK; audioEndpointInner->CheckStandBy(); EXPECT_EQ(audioEndpointInner->endpointStatus_, AudioEndpointInner::IDEL); } @@ -1343,5 +1377,426 @@ HWTEST(AudioEndpointInnerUnitTest, IsDualStream_002, TestSize.Level1) CaptureInfo capInfo; EXPECT_EQ(AudioEndpointInner::IsDualStream(capInfo), false); } + +/** + * @tc.name : Test AddCaptureInjector API + * @tc.type : FUNC + * @tc.number: AddCaptureInjector_001 + * @tc.desc : Test AddCaptureInjector with valid VOICE_COMMUNICATION source type and matching sink port index. + */ +HWTEST(AudioEndpointInnerUnitTest, AddCaptureInjector_001, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_VOIP_MMAP); + + // Set up required member variables + audioEndpointInner->dstStreamInfo_.samplingRate = SAMPLE_RATE_48000; + audioEndpointInner->dstStreamInfo_.format = SAMPLE_S16LE; + audioEndpointInner->dstStreamInfo_.channels = STEREO; + + // Mock injector to return expected values + EXPECT_CALL(*MockAudioInjector::GetMockInstance(), GetSinkPortIdx()) + .WillOnce(Return(1234)); + EXPECT_CALL(*MockAudioInjector::GetMockInstance(), GetModuleInfo()) + .WillOnce(Return(AudioModuleInfo{})); + EXPECT_CALL(*MockAudioInjector::GetMockInstance(), UpdateAudioInfo(_)) + .Times(1); + + uint32_t sinkPortIndex = 1234; + SourceType sourceType = SOURCE_TYPE_VOICE_COMMUNICATION; + + int32_t result = audioEndpointInner->AddCaptureInjector(sinkPortIndex, sourceType); + + EXPECT_EQ(result, SUCCESS); + EXPECT_TRUE(audioEndpointInner->isNeedInject_); + EXPECT_EQ(audioEndpointInner->injectSinkPortIdx_, sinkPortIndex); +} + +/** + * @tc.name : Test AddCaptureInjector API + * @tc.type : FUNC + * @tc.number: AddCaptureInjector_002 + * @tc.desc : Test AddCaptureInjector with invalid source type, should return ERROR. + */ +HWTEST(AudioEndpointInnerUnitTest, AddCaptureInjector_002, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_VOIP_MMAP); + + uint32_t sinkPortIndex = 1234; + SourceType sourceType = SOURCE_TYPE_MIC; // Invalid source type + + int32_t result = audioEndpointInner->AddCaptureInjector(sinkPortIndex, sourceType); + + EXPECT_EQ(result, ERROR); + EXPECT_FALSE(audioEndpointInner->isNeedInject_); + EXPECT_NE(audioEndpointInner->injectSinkPortIdx_, sinkPortIndex); +} + +/** + * @tc.name : Test AddCaptureInjector API + * @tc.type : FUNC + * @tc.number: AddCaptureInjector_003 + * @tc.desc : Test AddCaptureInjector with mismatched sink port index, should return ERROR. + */ +HWTEST(AudioEndpointInnerUnitTest, AddCaptureInjector_003, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_VOIP_MMAP); + + // Mock injector to return different port index + EXPECT_CALL(*MockAudioInjector::GetMockInstance(), GetSinkPortIdx()) + .WillOnce(Return(5678)); // Different from input + + uint32_t sinkPortIndex = 1234; + SourceType sourceType = SOURCE_TYPE_VOICE_COMMUNICATION; + int32_t result = audioEndpointInner->AddCaptureInjector(sinkPortIndex, sourceType); + + EXPECT_EQ(result, ERROR); + EXPECT_FALSE(audioEndpointInner->isNeedInject_); + EXPECT_NE(audioEndpointInner->injectSinkPortIdx_, sinkPortIndex); +} + +/** + * @tc.name : Test RemoveCaptureInjector API + * @tc.type : FUNC + * @tc.number: RemoveCaptureInjector_001 + * @tc.desc : Test RemoveCaptureInjector with valid VOICE_COMMUNICATION source type and matching sink port index. + */ +HWTEST(AudioEndpointInnerUnitTest, RemoveCaptureInjector_001, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_VOIP_MMAP); + + // Set up initial state + audioEndpointInner->isNeedInject_ = true; + audioEndpointInner->injectSinkPortIdx_ = 1234; + + uint32_t sinkPortIndex = 1234; + SourceType sourceType = SOURCE_TYPE_VOICE_COMMUNICATION; + + int32_t result = audioEndpointInner->RemoveCaptureInjector(sinkPortIndex, sourceType); + + EXPECT_EQ(result, SUCCESS); + EXPECT_FALSE(audioEndpointInner->isNeedInject_); + EXPECT_EQ(audioEndpointInner->injectSinkPortIdx_, UINT32_INVALID_VALUE); +} + +/** + * @tc.name : Test RemoveCaptureInjector API + * @tc.type : FUNC + * @tc.number: RemoveCaptureInjector_002 + * @tc.desc : Test RemoveCaptureInjector with invalid source type, should return ERROR. + */ +HWTEST(AudioEndpointInnerUnitTest, RemoveCaptureInjector_002, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_VOIP_MMAP); + + // Set up initial state + audioEndpointInner->isNeedInject_ = true; + audioEndpointInner->injectSinkPortIdx_ = 1234; + + uint32_t sinkPortIndex = 1234; + SourceType sourceType = SOURCE_TYPE_MIC; // Invalid source type + + int32_t result = audioEndpointInner->RemoveCaptureInjector(sinkPortIndex, sourceType); + + EXPECT_EQ(result, ERROR); + EXPECT_TRUE(audioEndpointInner->isNeedInject_); // Should remain unchanged + EXPECT_EQ(audioEndpointInner->injectSinkPortIdx_, 1234); // Should remain unchanged +} + +/** + * @tc.name : Test RemoveCaptureInjector API + * @tc.type : FUNC + * @tc.number: RemoveCaptureInjector_003 + * @tc.desc : Test RemoveCaptureInjector with mismatched sink port index, should return ERROR. + */ +HWTEST(AudioEndpointInnerUnitTest, RemoveCaptureInjector_003, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_VOIP_MMAP); + + // Set up initial state + audioEndpointInner->isNeedInject_ = true; + audioEndpointInner->injectSinkPortIdx_ = 1234; + + uint32_t sinkPortIndex = 5678; // Different from stored index + SourceType sourceType = SOURCE_TYPE_VOICE_COMMUNICATION; + + int32_t result = audioEndpointInner->RemoveCaptureInjector(sinkPortIndex, sourceType); + + EXPECT_EQ(result, ERROR); + EXPECT_TRUE(audioEndpointInner->isNeedInject_); // Should remain unchanged + EXPECT_EQ(audioEndpointInner->injectSinkPortIdx_, 1234); // Should remain unchanged +} + +/** + * @tc.name : Test AddRemoveCaptureInjector API sequence + * @tc.type : FUNC + * @tc.number: AddRemoveCaptureInjector_001 + * @tc.desc : Test sequential Add and Remove operations with valid parameters. + */ +HWTEST(AudioEndpointInnerUnitTest, AddRemoveCaptureInjector_001, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_MMAP); + + // Set up required member variables + audioEndpointInner->dstStreamInfo_.samplingRate = SAMPLE_RATE_48000; + audioEndpointInner->dstStreamInfo_.format = SAMPLE_S16LE; + audioEndpointInner->dstStreamInfo_.channels = STEREO; + + // Mock injector calls + EXPECT_CALL(*MockAudioInjector::GetMockInstance(), GetSinkPortIdx()) + .WillRepeatedly(Return(1234)); + EXPECT_CALL(*MockAudioInjector::GetMockInstance(), GetModuleInfo()) + .WillRepeatedly(Return(AudioModuleInfo{})); + + uint32_t sinkPortIndex = 1234; + SourceType sourceType = SOURCE_TYPE_VOICE_COMMUNICATION; + + // Test multiple add/remove cycles + for (int i = 0; i < 3; i++) { + // Add injector + int32_t addResult = audioEndpointInner->AddCaptureInjector(sinkPortIndex, sourceType); + EXPECT_EQ(addResult, SUCCESS); + EXPECT_TRUE(audioEndpointInner->isNeedInject_); + EXPECT_EQ(audioEndpointInner->injectSinkPortIdx_, sinkPortIndex); + + // Remove injector + int32_t removeResult = audioEndpointInner->RemoveCaptureInjector(sinkPortIndex, sourceType); + EXPECT_EQ(removeResult, SUCCESS); + EXPECT_FALSE(audioEndpointInner->isNeedInject_); + EXPECT_EQ(audioEndpointInner->injectSinkPortIdx_, UINT32_INVALID_VALUE); + } +} + +/** + * @tc.name : Test InjectToCaptureDataProc API + * @tc.type : FUNC + * @tc.number: InjectToCaptureDataProc_001 + * @tc.desc : Test InjectToCaptureDataProc with injection not needed, should return early. + */ +HWTEST(AudioEndpointInnerUnitTest, InjectToCaptureDataProc_001, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_VOIP_MMAP); + + SetInjectEnable(true); + audioEndpointInner->isNeedInject_ = false; + + BufferDesc readBuf = {nullptr, 1024}; + audioEndpointInner->InjectToCaptureDataProc(readBuf); + + // Should return early without processing + EXPECT_FALSE(audioEndpointInner->isConvertReadFormat_); +} + +/** + * @tc.name : Test InjectToCaptureDataProc API + * @tc.type : FUNC + * @tc.number: InjectToCaptureDataProc_002 + * @tc.desc : Test InjectToCaptureDataProc with wrong endpoint type, should return early. + */ +HWTEST(AudioEndpointInnerUnitTest, InjectToCaptureDataProc_002, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_MMAP); + + SetInjectEnable(true); + audioEndpointInner->isNeedInject_ = true; + audioEndpointInner->endpointType_ = AudioEndpoint::TYPE_MMAP; // Not VOIP_MMAP + + BufferDesc readBuf = {nullptr, 1024}; + audioEndpointInner->InjectToCaptureDataProc(readBuf); + + // Should return early without processing + EXPECT_FALSE(audioEndpointInner->isConvertReadFormat_); +} + +/** + * @tc.name : Test InjectToCaptureDataProc API + * @tc.type : FUNC + * @tc.number: InjectToCaptureDataProc_003 + * @tc.desc : Test InjectToCaptureDataProc with successful injection processing. + */ +HWTEST(AudioEndpointInnerUnitTest, InjectToCaptureDataProc_003, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_VOIP_MMAP); + + // Set up required state + audioEndpointInner->isNeedInject_ = true; + audioEndpointInner->endpointType_ = AudioEndpoint::TYPE_VOIP_MMAP; + audioEndpointInner->dstStreamInfo_.channels = STEREO; + audioEndpointInner->dstStreamInfo_.format = SAMPLE_S16LE; + audioEndpointInner->dstStreamInfo_.samplingRate = SAMPLE_RATE_48000; + audioEndpointInner->injectSinkPortIdx_ = 1234; + audioEndpointInner->fastCaptureId_ = 1; + + // Mock all external dependencies + SetInjectEnable(true); + EXPECT_CALL(*MockAudioInjector::GetMockInstance(), PeekAudioData(_, _, _, _)) + .WillOnce(Return(SUCCESS)); + + EXPECT_CALL(*MockFormatConverter::GetMockInstance(), S16StereoToF32Stereo(_, _)) + .Times(2) + .WillRepeatedly(Return(SUCCESS)); + + EXPECT_CALL(*MockHPAE::GetMockInstance(), SimdPointByPointAdd(_, _, _, _)) + .Times(1); + + EXPECT_CALL(*MockAudioLimiter::GetMockInstance(), SetConfig(_, _, _, _)) + .WillOnce(Return(SUCCESS)); + + EXPECT_CALL(*MockAudioLimiter::GetMockInstance(), Process(_, _, _)) + .WillOnce(Return(SUCCESS)); + + // Create test buffer + std::vector testBuffer(1024, 0); + BufferDesc readBuf = {testBuffer.data(), testBuffer.size()}; + + audioEndpointInner->InjectToCaptureDataProc(readBuf); + + // Should complete processing successfully + EXPECT_TRUE(audioEndpointInner->isConvertReadFormat_); +} + +/** + * @tc.name : Test InjectToCaptureDataProc API + * @tc.type : FUNC + * @tc.number: InjectToCaptureDataProc_004 + * @tc.desc : Test InjectToCaptureDataProc with PeekRendererInjectData failure. + */ +HWTEST(AudioEndpointInnerUnitTest, InjectToCaptureDataProc_004, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_VOIP_MMAP); + + // Set up required state + audioEndpointInner->isNeedInject_ = true; + audioEndpointInner->endpointType_ = AudioEndpoint::TYPE_VOIP_MMAP; + audioEndpointInner->injectSinkPortIdx_ = 1234; + + SetInjectEnable(true); + EXPECT_CALL(*MockAudioInjector::GetMockInstance(), PeekAudioData(_, _, _, _)) + .WillOnce(Return(ERROR)); // Peek fails + + BufferDesc readBuf = {nullptr, 1024}; + audioEndpointInner->InjectToCaptureDataProc(readBuf); + + // Should return early due to peek failure + EXPECT_FALSE(audioEndpointInner->isConvertReadFormat_); +} + +/** + * @tc.name : Test InjectToCaptureDataProc API + * @tc.type : FUNC + * @tc.number: InjectToCaptureDataProc_005 + * @tc.desc : Test InjectToCaptureDataProc with ConvertDataFormat failure. + */ +HWTEST(AudioEndpointInnerUnitTest, InjectToCaptureDataProc_005, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_VOIP_MMAP); + + // Set up required state + audioEndpointInner->isNeedInject_ = true; + audioEndpointInner->endpointType_ = AudioEndpoint::TYPE_VOIP_MMAP; + audioEndpointInner->dstStreamInfo_.channels = MONO; // Different from renderer + audioEndpointInner->dstStreamInfo_.format = SAMPLE_S16LE; + audioEndpointInner->dstStreamInfo_.samplingRate = SAMPLE_RATE_48000; + audioEndpointInner->injectSinkPortIdx_ = 1234; + + SetInjectEnable(true); + EXPECT_CALL(*MockAudioInjector::GetMockInstance(), PeekAudioData(_, _, _, _)) + .WillOnce(DoAll( + SetArgPointee<3>(AudioStreamInfo{STEREO, SAMPLE_S16LE, SAMPLE_RATE_48000}), + Return(SUCCESS) + )); + + BufferDesc readBuf = {nullptr, 1024}; + audioEndpointInner->InjectToCaptureDataProc(readBuf); + + // Should return early due to format conversion failure (channel mismatch) + EXPECT_FALSE(audioEndpointInner->isConvertReadFormat_); +} + +/** + * @tc.name : Test InjectToCaptureDataProc API + * @tc.type : FUNC + * @tc.number: InjectToCaptureDataProc_006 + * @tc.desc : Test InjectToCaptureDataProc with limiter creation failure. + */ +HWTEST(AudioEndpointInnerUnitTest, InjectToCaptureDataProc_006, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_VOIP_MMAP); + + // Set up required state + audioEndpointInner->isNeedInject_ = true; + audioEndpointInner->endpointType_ = AudioEndpoint::TYPE_VOIP_MMAP; + audioEndpointInner->dstStreamInfo_.channels = STEREO; + audioEndpointInner->dstStreamInfo_.format = SAMPLE_S16LE; + audioEndpointInner->dstStreamInfo_.samplingRate = SAMPLE_RATE_48000; + audioEndpointInner->injectSinkPortIdx_ = 1234; + audioEndpointInner->fastCaptureId_ = 1; + + SetInjectEnable(true); + EXPECT_CALL(*MockAudioInjector::GetMockInstance(), PeekAudioData(_, _, _, _)) + .WillOnce(DoAll( + SetArgPointee<3>(AudioStreamInfo{STEREO, SAMPLE_S16LE, SAMPLE_RATE_48000}), + Return(SUCCESS) + )); + + EXPECT_CALL(*MockFormatConverter::GetMockInstance(), S16StereoToF32Stereo(_, _)) + .Times(2) + .WillRepeatedly(Return(SUCCESS)); + + EXPECT_CALL(*MockHPAE::GetMockInstance(), SimdPointByPointAdd(_, _, _, _)) + .Times(1); + + EXPECT_CALL(*MockAudioLimiter::GetMockInstance(), SetConfig(_, _, _, _)) + .WillOnce(Return(ERROR)); // Limiter config fails + + BufferDesc readBuf = {nullptr, 1024}; + audioEndpointInner->InjectToCaptureDataProc(readBuf); + + // Should return early due to limiter failure + EXPECT_FALSE(audioEndpointInner->isConvertReadFormat_); +} + +/** + * @tc.name : Test InjectToCaptureDataProc API + * @tc.type : FUNC + * @tc.number: InjectToCaptureDataProc_007 + * @tc.desc : Test InjectToCaptureDataProc with limiter processing failure. + */ +HWTEST(AudioEndpointInnerUnitTest, InjectToCaptureDataProc_007, TestSize.Level1) +{ + std::shared_ptr audioEndpointInner = CreateInputEndpointInner(AudioEndpoint::TYPE_VOIP_MMAP); + + // Set up required state + audioEndpointInner->isNeedInject_ = true; + audioEndpointInner->endpointType_ = AudioEndpoint::TYPE_VOIP_MMAP; + audioEndpointInner->dstStreamInfo_.channels = STEREO; + audioEndpointInner->dstStreamInfo_.format = SAMPLE_S16LE; + audioEndpointInner->dstStreamInfo_.samplingRate = SAMPLE_RATE_48000; + audioEndpointInner->injectSinkPortIdx_ = 1234; + audioEndpointInner->fastCaptureId_ = 1; + audioEndpointInner->limiter_ = std::make_shared(1); // Limiter already exists + + SetInjectEnable(true); + EXPECT_CALL(*MockAudioInjector::GetMockInstance(), PeekAudioData(_, _, _, _)) + .WillOnce(DoAll( + SetArgPointee<3>(AudioStreamInfo{STEREO, SAMPLE_S16LE, SAMPLE_RATE_48000}), + Return(SUCCESS) + )); + + EXPECT_CALL(*MockFormatConverter::GetMockInstance(), S16StereoToF32Stereo(_, _)) + .Times(2) + .WillRepeatedly(Return(SUCCESS)); + + EXPECT_CALL(*MockHPAE::GetMockInstance(), SimdPointByPointAdd(_, _, _, _)) + .Times(1); + + EXPECT_CALL(*MockAudioLimiter::GetMockInstance(), Process(_, _, _)) + .WillOnce(Return(ERROR)); // Limiter process fails + + BufferDesc readBuf = {nullptr, 1024}; + audioEndpointInner->InjectToCaptureDataProc(readBuf); + + // Should return early due to limiter process failure + EXPECT_FALSE(audioEndpointInner->isConvertReadFormat_); +} } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/test/unittest/audio_process_in_server_unit_test.cpp b/services/audio_service/test/unittest/audio_process_in_server_unit_test.cpp index e43d31f50e..c8d0d18f14 100644 --- a/services/audio_service/test/unittest/audio_process_in_server_unit_test.cpp +++ b/services/audio_service/test/unittest/audio_process_in_server_unit_test.cpp @@ -18,6 +18,7 @@ #include "audio_errors.h" #include "audio_service.h" #include "audio_device_info.h" +#include "oh_audio_buffer.h" using namespace testing::ext; @@ -1187,5 +1188,749 @@ HWTEST(AudioProcessInServerUnitTest, GetSpanSizeInFrame_001, TestSize.Level4) uint32_t ret = audioProcessInServerRet.GetSpanSizeInFrame(); EXPECT_EQ(ret, audioProcessInServerRet.spanSizeInframe_); } + +#ifdef ENABLE_INJECT +class MockOHAudioBufferBase : public OHAudioBufferBase { +public: + MOCK_METHOD(int32_t, GetWritableDataFrames, (), (override)); + MOCK_METHOD(uint64_t, GetCurWriteFrame, (), (override)); + MOCK_METHOD(int32_t, GetAllWritableBufferFromPosFrame, (uint64_t, RingBufferWrapper&), (override)); + MOCK_METHOD(void, GetSizeParameter, (uint32_t&, uint32_t&), (override)); + MOCK_METHOD(void, SetHandleInfo, (uint64_t, uint64_t), (override)); + MOCK_METHOD(int32_t, SetCurWriteFrame, (uint64_t), (override)); +}; + +class MockAudioProcessInServer : public AudioProcessInServer { +public: + using AudioProcessInServer::AudioProcessInServer; + MOCK_METHOD(int32_t, HandleCapturerDataParams, (RingBufferWrapper&, AudioCaptureDataProcParams&), ()); + MOCK_METHOD(bool, GetMuteState, (), (const)); +}; + +// Mock classes for dependencies +class MockFormatConverter { +public: + static MockFormatConverter* GetMockInstance() + { + static MockFormatConverter instance; + return &instance; + } + + MOCK_METHOD(FormatHandlerMap, GetFormatHandlers, ()); + MOCK_METHOD(int32_t, S16StereoToF32Stereo, (const BufferDesc&, BufferDesc&)); +}; + +class MockProResampler { +public: + static MockProResampler* GetMockInstance() + { + static MockProResampler instance; + return &instance; + } + + MOCK_METHOD(int32_t, Process, (const float*, uint32_t, float*, uint32_t)); +}; + +class MockRingBufferWrapper { +public: + static MockRingBufferWrapper* GetMockInstance() + { + static MockRingBufferWrapper instance; + return &instance; + } + + MOCK_METHOD(int32_t, Write, (const uint8_t*, size_t)); +}; + +/** + * @tc.name : Test WriteToSpecialProcBuf API + * @tc.type : FUNC + * @tc.number: WriteToSpecialProcBuf_001 + * @tc.desc : Test WriteToSpecialProcBuf with null process buffer. + */ +HWTEST(AudioProcessInServerUnitTest, WriteToSpecialProcBuf_001, TestSize.Level1) +{ + AudioProcessConfig config = InitProcessConfig(); + AudioService* service = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServer(config, service); + + AudioCaptureDataProcParams procParams; + procParams.procBuf_ = nullptr; // Set null process buffer + + auto result = audioProcessInServer.WriteToSpecialProcBuf(procParams); + EXPECT_EQ(result, ERR_INVALID_HANDLE); +} + +/** + * @tc.name : Test WriteToSpecialProcBuf API + * @tc.type : FUNC + * @tc.number: WriteToSpecialProcBuf_002 + * @tc.desc : Test WriteToSpecialProcBuf with insufficient writable size. + */ +HWTEST(AudioProcessInServerUnitTest, WriteToSpecialProcBuf_002, TestSize.Level1) +{ + AudioProcessConfig config = InitProcessConfig(); + AudioService* service = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServer(config, service); + + AudioCaptureDataProcParams procParams; + auto mockProcBuf = std::make_shared(); + procParams.procBuf_ = mockProcBuf; + procParams.dstSpanSizeInframe_ = 100; // Request more frames than available + + // Mock GetWritableDataFrames to return insufficient size + EXPECT_CALL(*mockProcBuf, GetWritableDataFrames()).WillOnce(Return(50)); + EXPECT_CALL(*mockProcBuf, GetCurWriteFrame()).WillOnce(Return(0)); + + auto result = audioProcessInServer.WriteToSpecialProcBuf(procParams); + EXPECT_EQ(result, ERR_OPERATION_FAILED); +} + +/** + * @tc.name : Test WriteToSpecialProcBuf API + * @tc.type : FUNC + * @tc.number: WriteToSpecialProcBuf_003 + * @tc.desc : Test WriteToSpecialProcBuf with GetAllWritableBufferFromPosFrame failure. + */ +HWTEST(AudioProcessInServerUnitTest, WriteToSpecialProcBuf_003, TestSize.Level1) +{ + AudioProcessConfig config = InitProcessConfig(); + AudioService* service = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServer(config, service); + + AudioCaptureDataProcParams procParams; + auto mockProcBuf = std::make_shared(); + procParams.procBuf_ = mockProcBuf; + procParams.dstSpanSizeInframe_ = 50; + + // Mock sufficient writable frames + EXPECT_CALL(*mockProcBuf, GetWritableDataFrames()).WillOnce(Return(100)); + EXPECT_CALL(*mockProcBuf, GetCurWriteFrame()).WillOnce(Return(0)); + // Mock GetAllWritableBufferFromPosFrame to fail + EXPECT_CALL(*mockProcBuf, GetAllWritableBufferFromPosFrame(_, _)).WillOnce(Return(ERR_OPERATION_FAILED)); + + auto result = audioProcessInServer.WriteToSpecialProcBuf(procParams); + EXPECT_EQ(result, ERR_OPERATION_FAILED); +} + +/** + * @tc.name : Test WriteToSpecialProcBuf API + * @tc.type : FUNC + * @tc.number: WriteToSpecialProcBuf_004 + * @tc.desc : Test WriteToSpecialProcBuf with zero byteSizePerFrame. + */ +HWTEST(AudioProcessInServerUnitTest, WriteToSpecialProcBuf_004, TestSize.Level1) +{ + AudioProcessConfig config = InitProcessConfig(); + AudioService* service = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServer(config, service); + + AudioCaptureDataProcParams procParams; + auto mockProcBuf = std::make_shared(); + procParams.procBuf_ = mockProcBuf; + procParams.dstSpanSizeInframe_ = 50; + + // Mock sufficient writable frames + EXPECT_CALL(*mockProcBuf, GetWritableDataFrames()).WillOnce(Return(100)); + EXPECT_CALL(*mockProcBuf, GetCurWriteFrame()).WillOnce(Return(0)); + // Mock GetAllWritableBufferFromPosFrame to succeed + EXPECT_CALL(*mockProcBuf, GetAllWritableBufferFromPosFrame(_, _)).WillOnce(Return(SUCCESS)); + // Mock GetSizeParameter to return zero byteSizePerFrame + EXPECT_CALL(*mockProcBuf, GetSizeParameter(_, _)).WillOnce(DoAll(SetArgReferee<0>(1000), SetArgReferee<1>(0))); + + auto result = audioProcessInServer.WriteToSpecialProcBuf(procParams); + EXPECT_EQ(result, ERR_OPERATION_FAILED); +} + +/** + * @tc.name : Test WriteToSpecialProcBuf API + * @tc.type : FUNC + * @tc.number: WriteToSpecialProcBuf_005 + * @tc.desc : Test WriteToSpecialProcBuf with mute state enabled, should set buffer to zero. + */ +HWTEST(AudioProcessInServerUnitTest, WriteToSpecialProcBuf_005, TestSize.Level1) +{ + AudioProcessConfig config = InitProcessConfig(); + AudioService* service = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServer(config, service); + + // Enable mute state + audioProcessInServer.muteFlag_ = true; + + AudioCaptureDataProcParams procParams; + auto mockProcBuf = std::make_shared(); + procParams.procBuf_ = mockProcBuf; + procParams.dstSpanSizeInframe_ = 50; + + // Mock sufficient writable frames + EXPECT_CALL(*mockProcBuf, GetWritableDataFrames()).WillOnce(Return(100)); + EXPECT_CALL(*mockProcBuf, GetCurWriteFrame()).WillOnce(Return(0)); + // Mock GetAllWritableBufferFromPosFrame to succeed + EXPECT_CALL(*mockProcBuf, GetAllWritableBufferFromPosFrame(_, _)).WillOnce(Return(SUCCESS)); + // Mock GetSizeParameter to return valid parameters + EXPECT_CALL(*mockProcBuf, GetSizeParameter(_, _)).WillOnce(DoAll(SetArgReferee<0>(1000), SetArgReferee<1>(4))); + // Mock RingBufferWrapper SetBuffersValueWithSpecifyDataLen for mute + // Note: This requires mocking the RingBufferWrapper behavior + EXPECT_CALL(*mockProcBuf, SetHandleInfo(_, _)).Times(1); + EXPECT_CALL(*mockProcBuf, SetCurWriteFrame(_)).WillOnce(Return(SUCCESS)); + + auto result = audioProcessInServer.WriteToSpecialProcBuf(procParams); + EXPECT_EQ(result, SUCCESS); +} + +/** + * @tc.name : Test WriteToSpecialProcBuf API + * @tc.type : FUNC + * @tc.number: WriteToSpecialProcBuf_006 + * @tc.desc : Test WriteToSpecialProcBuf with HandleCapturerDataParams failure. + */ +HWTEST(AudioProcessInServerUnitTest, WriteToSpecialProcBuf_006, TestSize.Level1) +{ + AudioProcessConfig config = InitProcessConfig(); + AudioService* service = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServer(config, service); + + // Disable mute state to trigger HandleCapturerDataParams + audioProcessInServer.muteFlag_ = false; + + AudioCaptureDataProcParams procParams; + auto mockProcBuf = std::make_shared(); + procParams.procBuf_ = mockProcBuf; + procParams.dstSpanSizeInframe_ = 50; + + // Mock sufficient writable frames + EXPECT_CALL(*mockProcBuf, GetWritableDataFrames()).WillOnce(Return(100)); + EXPECT_CALL(*mockProcBuf, GetCurWriteFrame()).WillOnce(Return(0)); + // Mock GetAllWritableBufferFromPosFrame to succeed + EXPECT_CALL(*mockProcBuf, GetAllWritableBufferFromPosFrame(_, _)).WillOnce(Return(SUCCESS)); + // Mock GetSizeParameter to return valid parameters + EXPECT_CALL(*mockProcBuf, GetSizeParameter(_, _)).WillOnce(DoAll(SetArgReferee<0>(1000), SetArgReferee<1>(4))); + // Mock HandleCapturerDataParams to fail + EXPECT_CALL(audioProcessInServer, HandleCapturerDataParams(_, _)).WillOnce(Return(ERR_OPERATION_FAILED)); + + auto result = audioProcessInServer.WriteToSpecialProcBuf(procParams); + EXPECT_EQ(result, ERR_WRITE_FAILED); +} + +/** + * @tc.name : Test WriteToSpecialProcBuf API + * @tc.type : FUNC + * @tc.number: WriteToSpecialProcBuf_007 + * @tc.desc : Test WriteToSpecialProcBuf with SetCurWriteFrame failure. + */ +HWTEST(AudioProcessInServerUnitTest, WriteToSpecialProcBuf_007, TestSize.Level1) +{ + AudioProcessConfig config = InitProcessConfig(); + AudioService* service = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServer(config, service); + + // Disable mute state + audioProcessInServer.muteFlag_ = false; + + AudioCaptureDataProcParams procParams; + auto mockProcBuf = std::make_shared(); + procParams.procBuf_ = mockProcBuf; + procParams.dstSpanSizeInframe_ = 50; + + // Mock sufficient writable frames + EXPECT_CALL(*mockProcBuf, GetWritableDataFrames()).WillOnce(Return(100)); + EXPECT_CALL(*mockProcBuf, GetCurWriteFrame()).WillOnce(Return(0)); + // Mock GetAllWritableBufferFromPosFrame to succeed + EXPECT_CALL(*mockProcBuf, GetAllWritableBufferFromPosFrame(_, _)).WillOnce(Return(SUCCESS)); + // Mock GetSizeParameter to return valid parameters + EXPECT_CALL(*mockProcBuf, GetSizeParameter(_, _)).WillOnce(DoAll(SetArgReferee<0>(1000), SetArgReferee<1>(4))); + // Mock HandleCapturerDataParams to succeed + EXPECT_CALL(audioProcessInServer, HandleCapturerDataParams(_, _)).WillOnce(Return(EOK)); + // Mock SetHandleInfo to succeed + EXPECT_CALL(*mockProcBuf, SetHandleInfo(_, _)).Times(1); + // Mock SetCurWriteFrame to fail + EXPECT_CALL(*mockProcBuf, SetCurWriteFrame(_)).WillOnce(Return(ERR_OPERATION_FAILED)); + + auto result = audioProcessInServer.WriteToSpecialProcBuf(procParams); + EXPECT_EQ(result, ERR_OPERATION_FAILED); +} + +/** + * @tc.name : Test WriteToSpecialProcBuf API + * @tc.type : FUNC + * @tc.number: WriteToSpecialProcBuf_008 + * @tc.desc : Test WriteToSpecialProcBuf successful execution. + */ +HWTEST(AudioProcessInServerUnitTest, WriteToSpecialProcBuf_008, TestSize.Level1) +{ + AudioProcessConfig config = InitProcessConfig(); + AudioService* service = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServer(config, service); + + // Disable mute state + audioProcessInServer.muteFlag_ = false; + + AudioCaptureDataProcParams procParams; + auto mockProcBuf = std::make_shared(); + procParams.procBuf_ = mockProcBuf; + procParams.dstSpanSizeInframe_ = 50; + + // Mock sufficient writable frames + EXPECT_CALL(*mockProcBuf, GetWritableDataFrames()).WillOnce(Return(100)); + EXPECT_CALL(*mockProcBuf, GetCurWriteFrame()).WillOnce(Return(0)); + // Mock GetAllWritableBufferFromPosFrame to succeed + EXPECT_CALL(*mockProcBuf, GetAllWritableBufferFromPosFrame(_, _)).WillOnce(Return(SUCCESS)); + // Mock GetSizeParameter to return valid parameters + EXPECT_CALL(*mockProcBuf, GetSizeParameter(_, _)).WillOnce(DoAll(SetArgReferee<0>(1000), SetArgReferee<1>(4))); + // Mock HandleCapturerDataParams to succeed + EXPECT_CALL(audioProcessInServer, HandleCapturerDataParams(_, _)).WillOnce(Return(EOK)); + // Mock SetHandleInfo and SetCurWriteFrame to succeed + EXPECT_CALL(*mockProcBuf, SetHandleInfo(_, _)).Times(1); + EXPECT_CALL(*mockProcBuf, SetCurWriteFrame(_)).WillOnce(Return(SUCCESS)); + + auto result = audioProcessInServer.WriteToSpecialProcBuf(procParams); + EXPECT_EQ(result, SUCCESS); +} + +/** + * @tc.name : Test SetCaptureStreamInfo API + * @tc.type : FUNC + * @tc.number: SetCaptureStreamInfo_001 + * @tc.desc : Test SetCaptureStreamInfo with isConvertReadFormat true, should set format to SAMPLE_F32LE. + */ +HWTEST(AudioProcessInServerUnitTest, SetCaptureStreamInfo_001, TestSize.Level1) +{ + AudioProcessConfig configRet = InitProcessConfig(); + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + AudioStreamInfo srcInfo = {}; + AudioCaptureDataProcParams procParams; + procParams.isConvertReadFormat_ = true; + procParams.srcSamplingRate = 48000; + + audioProcessInServerRet.SetCaptureStreamInfo(srcInfo, procParams); + + EXPECT_EQ(srcInfo.channels, STEREO); + EXPECT_EQ(srcInfo.format, SAMPLE_F32LE); + EXPECT_EQ(srcInfo.samplingRate, procParams.srcSamplingRate); +} + +/** + * @tc.name : Test SetCaptureStreamInfo API + * @tc.type : FUNC + * @tc.number: SetCaptureStreamInfo_002 + * @tc.desc : Test SetCaptureStreamInfo with isConvertReadFormat false, should set format to SAMPLE_S16LE. + */ +HWTEST(AudioProcessInServerUnitTest, SetCaptureStreamInfo_002, TestSize.Level1) +{ + AudioProcessConfig configRet = InitProcessConfig(); + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + AudioStreamInfo srcInfo = {}; + AudioCaptureDataProcParams procParams; + procParams.isConvertReadFormat_ = false; + procParams.srcSamplingRate = 44100; + + audioProcessInServerRet.SetCaptureStreamInfo(srcInfo, procParams); + + EXPECT_EQ(srcInfo.channels, STEREO); + EXPECT_EQ(srcInfo.format, SAMPLE_S16LE); + EXPECT_EQ(srcInfo.samplingRate, procParams.srcSamplingRate); +} + +/** + * @tc.name : Test CaptureDataResampleProcess API + * @tc.type : FUNC + * @tc.number: CaptureDataResampleProcess_001 + * @tc.desc : Test CaptureDataResampleProcess with same sample rate and no format conversion. + */ +HWTEST(AudioProcessInServerUnitTest, CaptureDataResampleProcess_001, TestSize.Level2) +{ + AudioProcessConfig configRet = InitProcessConfig(); + configRet.streamInfo.samplingRate = 48000; + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + size_t bufLen = 1024; + BufferDesc outBuf = {}; + AudioStreamInfo srcInfo; + srcInfo.samplingRate = 48000; + srcInfo.format = SAMPLE_S16LE; + srcInfo.channels = STEREO; + + AudioCaptureDataProcParams procParams; + procParams.isConvertReadFormat_ = false; + procParams.captureConvBuffer_.resize(bufLen); + + int32_t ret = audioProcessInServerRet.CaptureDataResampleProcess(bufLen, outBuf, srcInfo, procParams); + + EXPECT_EQ(ret, SUCCESS); + EXPECT_EQ(outBuf.buffer, nullptr); // No change when no resampling needed +} + +/** + * @tc.name : Test CaptureDataResampleProcess API + * @tc.type : FUNC + * @tc.number: CaptureDataResampleProcess_002 + * @tc.desc : Test CaptureDataResampleProcess with same sample rate and format conversion needed. + */ +HWTEST(AudioProcessInServerUnitTest, CaptureDataResampleProcess_002, TestSize.Level2) +{ + AudioProcessConfig configRet = InitProcessConfig(); + configRet.streamInfo.samplingRate = 48000; + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + size_t bufLen = 1024; + BufferDesc outBuf = {}; + AudioStreamInfo srcInfo; + srcInfo.samplingRate = 48000; + srcInfo.format = SAMPLE_S16LE; + srcInfo.channels = STEREO; + + AudioCaptureDataProcParams procParams; + procParams.isConvertReadFormat_ = true; + procParams.captureConvBuffer_.resize(bufLen); + + int32_t ret = audioProcessInServerRet.CaptureDataResampleProcess(bufLen, outBuf, srcInfo, procParams); + + EXPECT_EQ(ret, SUCCESS); + EXPECT_EQ(outBuf.buffer, procParams.captureConvBuffer_.data()); + EXPECT_EQ(outBuf.bufLength, bufLen); +} + +/** + * @tc.name : Test CaptureDataResampleProcess API + * @tc.type : FUNC + * @tc.number: CaptureDataResampleProcess_003 + * @tc.desc : Test CaptureDataResampleProcess with different sample rates and S16 format. + */ +HWTEST(AudioProcessInServerUnitTest, CaptureDataResampleProcess_003, TestSize.Level2) +{ + AudioProcessConfig configRet = InitProcessConfig(); + configRet.streamInfo.samplingRate = 44100; + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + size_t bufLen = 1024; + BufferDesc outBuf = {}; + AudioStreamInfo srcInfo; + srcInfo.samplingRate = 48000; + srcInfo.format = SAMPLE_S16LE; + srcInfo.channels = STEREO; + + AudioCaptureDataProcParams procParams; + procParams.isConvertReadFormat_ = false; + procParams.captureConvBuffer_.resize(bufLen); + procParams.rendererConvBuffer_.resize(bufLen); + + // Mock FormatConverter + EXPECT_CALL(*MockFormatConverter::GetMockInstance(), S16StereoToF32Stereo(_, _)) + .WillOnce(Return(SUCCESS)); + + // Mock Resampler + EXPECT_CALL(*MockProResampler::GetMockInstance(), Process(_, _, _, _)) + .WillOnce(Return(SUCCESS)); + + int32_t ret = audioProcessInServerRet.CaptureDataResampleProcess(bufLen, outBuf, srcInfo, procParams); + + EXPECT_EQ(ret, SUCCESS); + EXPECT_NE(outBuf.buffer, nullptr); +} + +/** + * @tc.name : Test CaptureDataResampleProcess API + * @tc.type : FUNC + * @tc.number: CaptureDataResampleProcess_004 + * @tc.desc : Test CaptureDataResampleProcess with different sample rates and F32 format. + */ +HWTEST(AudioProcessInServerUnitTest, CaptureDataResampleProcess_004, TestSize.Level2) +{ + AudioProcessConfig configRet = InitProcessConfig(); + configRet.streamInfo.samplingRate = 44100; + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + size_t bufLen = 1024; + BufferDesc outBuf = {}; + AudioStreamInfo srcInfo; + srcInfo.samplingRate = 48000; + srcInfo.format = SAMPLE_F32LE; + srcInfo.channels = STEREO; + + AudioCaptureDataProcParams procParams; + procParams.isConvertReadFormat_ = false; + procParams.captureConvBuffer_.resize(bufLen); + procParams.rendererConvBuffer_.resize(bufLen); + + // Mock Resampler + EXPECT_CALL(*MockProResampler::GetMockInstance(), Process(_, _, _, _)) + .WillOnce(Return(SUCCESS)); + + int32_t ret = audioProcessInServerRet.CaptureDataResampleProcess(bufLen, outBuf, srcInfo, procParams); + + EXPECT_EQ(ret, SUCCESS); + EXPECT_NE(outBuf.buffer, nullptr); +} + +/** + * @tc.name : Test CaptureDataResampleProcess API + * @tc.type : FUNC + * @tc.number: CaptureDataResampleProcess_005 + * @tc.desc : Test CaptureDataResampleProcess with resampler creation failure. + */ +HWTEST(AudioProcessInServerUnitTest, CaptureDataResampleProcess_005, TestSize.Level3) +{ + AudioProcessConfig configRet = InitProcessConfig(); + configRet.streamInfo.samplingRate = 44100; + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + size_t bufLen = 1024; + BufferDesc outBuf = {}; + AudioStreamInfo srcInfo; + srcInfo.samplingRate = 48000; + srcInfo.format = SAMPLE_F32LE; + srcInfo.channels = STEREO; + + AudioCaptureDataProcParams procParams; + procParams.isConvertReadFormat_ = false; + procParams.captureConvBuffer_.resize(bufLen); + procParams.rendererConvBuffer_.resize(bufLen); + + // Mock Resampler to return failure + EXPECT_CALL(*MockProResampler::GetMockInstance(), Process(_, _, _, _)) + .WillOnce(Return(ERROR)); + + int32_t ret = audioProcessInServerRet.CaptureDataResampleProcess(bufLen, outBuf, srcInfo, procParams); + + EXPECT_NE(ret, SUCCESS); +} + +/** + * @tc.name : Test CapturerDataFormatAndChnConv API + * @tc.type : FUNC + * @tc.number: CapturerDataFormatAndChnConv_001 + * @tc.desc : Test CapturerDataFormatAndChnConv with supported format conversion. + */ +HWTEST(AudioProcessInServerUnitTest, CapturerDataFormatAndChnConv_001, TestSize.Level2) +{ + AudioProcessConfig configRet = InitProcessConfig(); + configRet.streamInfo.format = SAMPLE_S16LE; + configRet.streamInfo.channels = STEREO; + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + RingBufferWrapper writeBuf; + BufferDesc resampleOutBuf; + resampleOutBuf.bufLength = 1024; + resampleOutBuf.buffer = new uint8_t[resampleOutBuf.bufLength]; + + AudioStreamInfo srcInfo; + srcInfo.format = SAMPLE_F32LE; + srcInfo.channels = STEREO; + + AudioStreamInfo dstInfo = configRet.streamInfo; + + // Mock format handler + FormatHandler mockHandler = [](BufferDesc&, BufferDesc&, bool& isDoConvert) { + isDoConvert = true; + return SUCCESS; + }; + + EXPECT_CALL(*MockFormatConverter::GetMockInstance(), GetFormatHandlers()) + .WillOnce(Return(FormatHandlerMap{{FormatKey{STEREO, SAMPLE_F32LE, STEREO, SAMPLE_S16LE}, mockHandler}})); + + EXPECT_CALL(*MockRingBufferWrapper::GetMockInstance(), Write(_, _)) + .WillOnce(Return(SUCCESS)); + + int32_t ret = audioProcessInServerRet.CapturerDataFormatAndChnConv(writeBuf, resampleOutBuf, srcInfo, dstInfo); + + EXPECT_EQ(ret, SUCCESS); + + delete[] resampleOutBuf.buffer; +} + +/** + * @tc.name : Test CapturerDataFormatAndChnConv API + * @tc.type : FUNC + * @tc.number: CapturerDataFormatAndChnConv_002 + * @tc.desc : Test CapturerDataFormatAndChnConv with no conversion needed. + */ +HWTEST(AudioProcessInServerUnitTest, CapturerDataFormatAndChnConv_002, TestSize.Level2) +{ + AudioProcessConfig configRet = InitProcessConfig(); + configRet.streamInfo.format = SAMPLE_S16LE; + configRet.streamInfo.channels = STEREO; + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + RingBufferWrapper writeBuf; + BufferDesc resampleOutBuf; + resampleOutBuf.bufLength = 1024; + resampleOutBuf.buffer = new uint8_t[resampleOutBuf.bufLength]; + + AudioStreamInfo srcInfo; + srcInfo.format = SAMPLE_S16LE; + srcInfo.channels = STEREO; + + AudioStreamInfo dstInfo = configRet.streamInfo; + + // Mock format handler that doesn't require conversion + FormatHandler mockHandler = [](BufferDesc&, BufferDesc&, bool& isDoConvert) { + isDoConvert = false; + return SUCCESS; + }; + + EXPECT_CALL(*MockFormatConverter::GetMockInstance(), GetFormatHandlers()) + .WillOnce(Return(FormatHandlerMap{{FormatKey{STEREO, SAMPLE_S16LE, STEREO, SAMPLE_S16LE}, mockHandler}})); + + EXPECT_CALL(*MockRingBufferWrapper::GetMockInstance(), Write(_, _)) + .WillOnce(Return(SUCCESS)); + + int32_t ret = audioProcessInServerRet.CapturerDataFormatAndChnConv(writeBuf, resampleOutBuf, srcInfo, dstInfo); + + EXPECT_EQ(ret, SUCCESS); + + delete[] resampleOutBuf.buffer; +} + +/** + * @tc.name : Test CapturerDataFormatAndChnConv API + * @tc.type : FUNC + * @tc.number: CapturerDataFormatAndChnConv_003 + * @tc.desc : Test CapturerDataFormatAndChnConv with unsupported format conversion. + */ +HWTEST(AudioProcessInServerUnitTest, CapturerDataFormatAndChnConv_003, TestSize.Level2) +{ + AudioProcessConfig configRet = InitProcessConfig(); + configRet.streamInfo.format = SAMPLE_S16LE; + configRet.streamInfo.channels = STEREO; + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + RingBufferWrapper writeBuf; + BufferDesc resampleOutBuf; + resampleOutBuf.bufLength = 1024; + resampleOutBuf.buffer = new uint8_t[resampleOutBuf.bufLength]; + + AudioStreamInfo srcInfo; + srcInfo.format = SAMPLE_S24LE; // Unsupported format + srcInfo.channels = STEREO; + + AudioStreamInfo dstInfo = configRet.streamInfo; + + EXPECT_CALL(*MockFormatConverter::GetMockInstance(), GetFormatHandlers()) + .WillOnce(Return(FormatHandlerMap{})); // Empty handler map + + int32_t ret = audioProcessInServerRet.CapturerDataFormatAndChnConv(writeBuf, resampleOutBuf, srcInfo, dstInfo); + + EXPECT_EQ(ret, ERR_NOT_SUPPORTED); + + delete[] resampleOutBuf.buffer; +} + +/** + * @tc.name : Test HandleCapturerDataParams API + * @tc.type : FUNC + * @tc.number: HandleCapturerDataParams_001 + * @tc.desc : Test HandleCapturerDataParams with successful processing. + */ +HWTEST(AudioProcessInServerUnitTest, HandleCapturerDataParams_001, TestSize.Level2) +{ + AudioProcessConfig configRet = InitProcessConfig(); + configRet.streamInfo.format = SAMPLE_S16LE; + configRet.streamInfo.channels = STEREO; + configRet.streamInfo.samplingRate = 48000; + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + RingBufferWrapper writeBuf; + AudioCaptureDataProcParams procParams; + procParams.readBuf_.bufLength = 512; + procParams.readBuf_.buffer = new uint8_t[procParams.readBuf_.bufLength]; + procParams.srcSamplingRate = 48000; + procParams.isConvertReadFormat_ = false; + procParams.captureConvBuffer_.resize(1024); + + // Mock all dependent methods + EXPECT_CALL(*MockFormatConverter::GetMockInstance(), GetFormatHandlers()) + .WillOnce(Return(FormatHandlerMap{})); + + EXPECT_CALL(*MockRingBufferWrapper::GetMockInstance(), Write(_, _)) + .WillOnce(Return(SUCCESS)); + + int32_t ret = audioProcessInServerRet.HandleCapturerDataParams(writeBuf, procParams); + + EXPECT_EQ(ret, SUCCESS); + + delete[] procParams.readBuf_.buffer; +} + +/** + * @tc.name : Test HandleCapturerDataParams API + * @tc.type : FUNC + * @tc.number: HandleCapturerDataParams_002 + * @tc.desc : Test HandleCapturerDataParams with resample failure. + */ +HWTEST(AudioProcessInServerUnitTest, HandleCapturerDataParams_002, TestSize.Level3) +{ + AudioProcessConfig configRet = InitProcessConfig(); + configRet.streamInfo.format = SAMPLE_S16LE; + configRet.streamInfo.channels = STEREO; + configRet.streamInfo.samplingRate = 44100; + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + RingBufferWrapper writeBuf; + AudioCaptureDataProcParams procParams; + procParams.readBuf_.bufLength = 512; + procParams.readBuf_.buffer = new uint8_t[procParams.readBuf_.bufLength]; + procParams.srcSamplingRate = 48000; + procParams.isConvertReadFormat_ = false; + procParams.captureConvBuffer_.resize(1024); + + // Mock resampler to return failure + EXPECT_CALL(*MockProResampler::GetMockInstance(), Process(_, _, _, _)) + .WillOnce(Return(ERROR)); + + int32_t ret = audioProcessInServerRet.HandleCapturerDataParams(writeBuf, procParams); + + EXPECT_NE(ret, SUCCESS); + + delete[] procParams.readBuf_.buffer; +} + +/** + * @tc.name : Test HandleCapturerDataParams API + * @tc.type : FUNC + * @tc.number: HandleCapturerDataParams_003 + * @tc.desc : Test HandleCapturerDataParams with format conversion failure. + */ +HWTEST(AudioProcessInServerUnitTest, HandleCapturerDataParams_003, TestSize.Level3) +{ + AudioProcessConfig configRet = InitProcessConfig(); + configRet.streamInfo.format = SAMPLE_S16LE; + configRet.streamInfo.channels = STEREO; + configRet.streamInfo.samplingRate = 48000; + AudioService* releaseCallbackRet = AudioService::GetInstance(); + AudioProcessInServer audioProcessInServerRet(configRet, releaseCallbackRet); + + RingBufferWrapper writeBuf; + AudioCaptureDataProcParams procParams; + procParams.readBuf_.bufLength = 512; + procParams.readBuf_.buffer = new uint8_t[procParams.readBuf_.bufLength]; + procParams.srcSamplingRate = 48000; + procParams.isConvertReadFormat_ = false; + procParams.captureConvBuffer_.resize(1024); + + // Mock format conversion to return failure + EXPECT_CALL(*MockFormatConverter::GetMockInstance(), GetFormatHandlers()) + .WillOnce(Return(FormatHandlerMap{})); + + int32_t ret = audioProcessInServerRet.HandleCapturerDataParams(writeBuf, procParams); + + EXPECT_NE(ret, SUCCESS); + + delete[] procParams.readBuf_.buffer; +} +#endif } // namespace AudioStandard } // namespace OHOS diff --git a/services/audio_service/test/unittest/audio_service_unit_test.cpp b/services/audio_service/test/unittest/audio_service_unit_test.cpp index 2c84f50be9..d34a5a9995 100644 --- a/services/audio_service/test/unittest/audio_service_unit_test.cpp +++ b/services/audio_service/test/unittest/audio_service_unit_test.cpp @@ -1562,7 +1562,7 @@ HWTEST(AudioServiceUnitTest, DelayCallReleaseEndpoint_001, TestSize.Level1) AudioService *audioService = AudioService::GetInstance(); AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_MMAP, - 123, clientConfig); + 123, clientConfig.audioMode); EXPECT_NE(nullptr, endpoint); string endpointName = endpoint->GetEndpointName(); audioService->endpointList_[endpointName] = endpoint; @@ -1667,7 +1667,7 @@ HWTEST(AudioServiceUnitTest, GetReleaseDelayTime_001, TestSize.Level1) AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_VOIP_MMAP, - 123, clientConfig); + 123, clientConfig.audioMode); EXPECT_NE(nullptr, endpoint); bool isSwitchStream = false; @@ -1690,7 +1690,7 @@ HWTEST(AudioServiceUnitTest, GetReleaseDelayTime_002, TestSize.Level1) AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_MMAP, - 123, clientConfig); + 123, clientConfig.audioMode); EXPECT_NE(nullptr, endpoint); bool isSwitchStream = false; @@ -1713,7 +1713,7 @@ HWTEST(AudioServiceUnitTest, GetReleaseDelayTime_003, TestSize.Level1) AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_MMAP, - 123, clientConfig); + 123, clientConfig.audioMode); EXPECT_NE(nullptr, endpoint); endpoint->deviceInfo_.deviceType_ = DEVICE_TYPE_BLUETOOTH_A2DP; @@ -1926,7 +1926,7 @@ HWTEST(AudioServiceUnitTest, FilterAllFastProcess_002, TestSize.Level1) AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_VOIP_MMAP, - 123, clientConfig); + 123, clientConfig.audioMode); EXPECT_NE(endpoint, nullptr); endpoint->deviceInfo_.deviceRole_ = OUTPUT_DEVICE; @@ -1959,7 +1959,7 @@ HWTEST(AudioServiceUnitTest, CheckDisableFastInner_001, TestSize.Level1) AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_VOIP_MMAP, - 123, clientConfig); + 123, clientConfig.audioMode); int32_t ret = audioService->CheckDisableFastInner(endpoint); EXPECT_EQ(ret, SUCCESS); @@ -1986,7 +1986,7 @@ HWTEST(AudioServiceUnitTest, HandleFastCapture_001, TestSize.Level1) AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_VOIP_MMAP, - 123, clientConfig); + 123, clientConfig.audioMode); EXPECT_NE(endpoint, nullptr); int32_t ret = audioService->HandleFastCapture(captureIds, audioprocess, endpoint); @@ -2206,9 +2206,9 @@ HWTEST(AudioServiceUnitTest, CheckBeforeRecordEndpointCreate_001, TestSize.Level std::string endpointName = "test"; AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_VOIP_MMAP, - 123, clientConfig); + 123, clientConfig.audioMode); EXPECT_NE(endpoint, nullptr); - endpoint->clientConfig_.audioMode = AudioMode::AUDIO_MODE_RECORD; + endpoint->audioMode_ = AudioMode::AUDIO_MODE_RECORD; AudioService::GetInstance()->endpointList_[endpointName] = endpoint; AudioService::GetInstance()->CheckBeforeRecordEndpointCreate(isRecord); } @@ -2225,9 +2225,9 @@ HWTEST(AudioServiceUnitTest, CheckBeforeRecordEndpointCreate_002, TestSize.Level std::string endpointName = "test"; AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_VOIP_MMAP, - 123, clientConfig); + 123, clientConfig.audioMode); EXPECT_NE(endpoint, nullptr); - endpoint->clientConfig_.audioMode = AudioMode::AUDIO_MODE_PLAYBACK; + endpoint->audioMode_ = AudioMode::AUDIO_MODE_PLAYBACK; AudioService::GetInstance()->endpointList_[endpointName] = endpoint; AudioService::GetInstance()->CheckBeforeRecordEndpointCreate(isRecord); } @@ -2265,7 +2265,7 @@ HWTEST(AudioServiceUnitTest, NotifyStreamVolumeChanged_002, TestSize.Level1) AudioService::GetInstance()->endpointList_.clear(); AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_VOIP_MMAP, - 123, clientConfig); + 123, clientConfig.audioMode); EXPECT_NE(endpoint, nullptr); AudioService::GetInstance()->endpointList_[endpointName] = endpoint; auto ret = AudioService::GetInstance()->NotifyStreamVolumeChanged(streamType, volume); @@ -2594,9 +2594,9 @@ HWTEST(AudioServiceUnitTest, ForceStopAudioStream_002, TestSize.Level1) audioprocess->sessionId_ = 1; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_VOIP_MMAP, - 123, config); + 123, config.audioMode); EXPECT_NE(endpoint, nullptr); - endpoint->clientConfig_.audioMode = AudioMode::AUDIO_MODE_PLAYBACK; + endpoint->audioMode_ = AudioMode::AUDIO_MODE_PLAYBACK; AudioService::GetInstance()->linkedPairedList_.push_back(std::make_pair(audioprocess, endpoint)); StopAudioType stopAudioType = STOP_ALL; @@ -3129,7 +3129,7 @@ HWTEST(AudioServiceUnitTest, LinkProcessToEndpoint_001, TestSize.Level1) sptr audioprocess = AudioProcessInServer::Create(config, AudioService::GetInstance()); EXPECT_NE(audioprocess, nullptr); std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_VOIP_MMAP, - 123, config); + 123, config.audioMode); EXPECT_NE(AudioService::GetInstance()->LinkProcessToEndpoint(audioprocess, endpoint), SUCCESS); } diff --git a/services/audio_service/test/unittest/format_converter_unit_test.cpp b/services/audio_service/test/unittest/format_converter_unit_test.cpp index 13e847807b..ae1d35b49d 100644 --- a/services/audio_service/test/unittest/format_converter_unit_test.cpp +++ b/services/audio_service/test/unittest/format_converter_unit_test.cpp @@ -32,6 +32,15 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); + + // Helper function to create BufferDesc + BufferDesc CreateBufferDesc(void* buffer, size_t bufLength) + { + BufferDesc desc; + desc.buffer = static_cast(buffer); + desc.bufLength = bufLength; + return desc; + } }; void FormatConverterUnitTest::SetUpTestCase(void) @@ -655,5 +664,367 @@ HWTEST_F(FormatConverterUnitTest, S16StereoToS16Mono_001, TestSize.Level1) EXPECT_EQ(*dstDescTest.buffer + 2, 4); EXPECT_EQ(*dstDescTest.buffer + 3, 5); } + +// Test normal case: stereo to mono conversion +HWTEST_F(FormatConverterUnitTest, F32StereoToF32Mono_NormalCase, TestSize.Level1) +{ + FormatConverter converter; + + // Create test data: stereo (left and right channels interleaved) + std::vector stereoData = { + 1.0f, 2.0f, // Frame 1: left=1.0, right=2.0 → mono=(1.0+2.0)/2=1.5 + 3.0f, 4.0f, // Frame 2: left=3.0, right=4.0 → mono=3.5 + 5.0f, 6.0f // Frame 3: left=5.0, right=6.0 → mono=5.5 + }; + + std::vector monoData(3); // Expected output: 3 mono samples + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(float)); + + int32_t result = converter.F32StereoToF32Mono(srcDesc, dstDesc); + + EXPECT_EQ(result, 0); + EXPECT_FLOAT_EQ(monoData[0], 1.5f); + EXPECT_FLOAT_EQ(monoData[1], 3.5f); + EXPECT_FLOAT_EQ(monoData[2], 5.5f); +} + +// Test null source buffer +HWTEST_F(FormatConverterUnitTest, F32StereoToF32Mono_NullSrcBuffer, TestSize.Level1) +{ + FormatConverter converter; + + std::vector stereoData(4); + std::vector monoData(2); + + BufferDesc srcDesc = CreateBufferDesc(nullptr, stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(float)); + + int32_t result = converter.F32StereoToF32Mono(srcDesc, dstDesc); + EXPECT_EQ(result, -1); +} + +// Test null destination buffer +HWTEST_F(FormatConverterUnitTest, F32StereoToF32Mono_NullDstBuffer, TestSize.Level1) +{ + FormatConverter converter; + + std::vector stereoData(4); + std::vector monoData(2); + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(nullptr, monoData.size() * sizeof(float)); + + int32_t result = converter.F32StereoToF32Mono(srcDesc, dstDesc); + EXPECT_EQ(result, -1); +} + +// Test zero-length buffers +HWTEST_F(FormatConverterUnitTest, F32StereoToF32Mono_ZeroLengthBuffer, TestSize.Level1) +{ + FormatConverter converter; + + std::vector stereoData(4); + std::vector monoData(2); + + // Test zero-length source buffer + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), 0); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(float)); + + int32_t result = converter.F32StereoToF32Mono(srcDesc, dstDesc); + EXPECT_EQ(result, -1); + + // Test zero-length destination buffer + srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + dstDesc = CreateBufferDesc(monoData.data(), 0); + + result = converter.F32StereoToF32Mono(srcDesc, dstDesc); + EXPECT_EQ(result, -1); +} + +// Test buffer length mismatch +HWTEST_F(FormatConverterUnitTest, F32StereoToF32Mono_BufferLengthMismatch, TestSize.Level1) +{ + FormatConverter converter; + + // Stereo data has 4 samples (2 frames), but destination buffer can only hold 1 mono sample + std::vector stereoData = {1.0f, 2.0f, 3.0f, 4.0f}; + std::vector monoData(1); // Too small, should need 2 mono samples + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(float)); + + int32_t result = converter.F32StereoToF32Mono(srcDesc, dstDesc); + EXPECT_EQ(result, -1); +} + +// Test edge case: single frame conversion +HWTEST_F(FormatConverterUnitTest, F32StereoToF32Mono_SingleFrame, TestSize.Level1) +{ + FormatConverter converter; + + std::vector stereoData = {10.0f, 20.0f}; // One stereo frame + std::vector monoData(1); + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(float)); + + int32_t result = converter.F32StereoToF32Mono(srcDesc, dstDesc); + + EXPECT_EQ(result, 0); + EXPECT_FLOAT_EQ(monoData[0], 15.0f); // (10+20)/2 = 15 +} + +// Test negative values +HWTEST_F(FormatConverterUnitTest, F32StereoToF32Mono_NegativeValues, TestSize.Level1) +{ + FormatConverter converter; + + std::vector stereoData = {-1.0f, 1.0f, -2.0f, 2.0f}; + std::vector monoData(2); + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(float)); + + int32_t result = converter.F32StereoToF32Mono(srcDesc, dstDesc); + + EXPECT_EQ(result, 0); + EXPECT_FLOAT_EQ(monoData[0], 0.0f); // (-1+1)/2 = 0 + EXPECT_FLOAT_EQ(monoData[1], 0.0f); // (-2+2)/2 = 0 +} + +// Test zero values +HWTEST_F(FormatConverterUnitTest, F32StereoToF32Mono_ZeroValues, TestSize.Level1) +{ + FormatConverter converter; + + std::vector stereoData = {0.0f, 0.0f, 0.0f, 0.0f}; + std::vector monoData(2); + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(float)); + + int32_t result = converter.F32StereoToF32Mono(srcDesc, dstDesc); + + EXPECT_EQ(result, 0); + EXPECT_FLOAT_EQ(monoData[0], 0.0f); + EXPECT_FLOAT_EQ(monoData[1], 0.0f); +} + +// Test large number of frames +HWTEST_F(FormatConverterUnitTest, F32StereoToF32Mono_MultipleFrames, TestSize.Level1) +{ + FormatConverter converter; + + const size_t frameCount = 1000; + std::vector stereoData(frameCount * 2); + std::vector monoData(frameCount); + + // Fill stereo data with pattern: left = index, right = index + 0.5 + for (size_t i = 0; i < frameCount; i++) { + stereoData[i * 2] = static_cast(i); // left channel + stereoData[i * 2 + 1] = static_cast(i) + 0.5f; // right channel + } + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(float)); + + int32_t result = converter.F32StereoToF32Mono(srcDesc, dstDesc); + + EXPECT_EQ(result, 0); + + // Verify each mono sample is the average of corresponding stereo frame + for (size_t i = 0; i < frameCount; i++) { + float expected = (static_cast(i) + static_cast(i) + 0.5f) / 2.0f; + EXPECT_FLOAT_EQ(monoData[i], expected); + } +} + +// Test normal case: stereo float32 to mono int16 conversion +HWTEST_F(FormatConverterUnitTest, F32StereoToS16Mono_NormalCase, TestSize.Level1) +{ + FormatConverter converter; + + // Create test data: stereo float32 (left and right channels interleaved) + std::vector stereoData = { + 1.0f, -1.0f, // Frame 1: left=1.0, right=-1.0 → mono=0.0 + 0.5f, -0.5f, // Frame 2: left=0.5, right=-0.5 → mono=0.0 + 0.8f, 0.2f // Frame 3: left=0.8, right=0.2 → mono=0.5 + }; + + // Expected output: 3 mono int16 samples + std::vector monoData(3); + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(int16_t)); + + int32_t result = converter.F32StereoToS16Mono(srcDesc, dstDesc); + + EXPECT_EQ(result, 0); + + // Verify conversion with proper scaling to int16 range + EXPECT_EQ(monoData[0], 0); // (1.0 + -1.0)/2 = 0.0 → 0 + EXPECT_EQ(monoData[1], 0); // (0.5 + -0.5)/2 = 0.0 → 0 + EXPECT_EQ(monoData[2], static_cast(0.5 * 32767)); // (0.8 + 0.2)/2 = 0.5 → 0.5 * 32767 +} + +// Test null source buffer +HWTEST_F(FormatConverterUnitTest, F32StereoToS16Mono_NullSrcBuffer, TestSize.Level1) +{ + FormatConverter converter; + + std::vector stereoData(4); + std::vector monoData(2); + + BufferDesc srcDesc = CreateBufferDesc(nullptr, stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(int16_t)); + + int32_t result = converter.F32StereoToS16Mono(srcDesc, dstDesc); + EXPECT_EQ(result, -1); +} + +// Test null destination buffer +HWTEST_F(FormatConverterUnitTest, F32StereoToS16Mono_NullDstBuffer, TestSize.Level1) +{ + FormatConverter converter; + + std::vector stereoData(4); + std::vector monoData(2); + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(nullptr, monoData.size() * sizeof(int16_t)); + + int32_t result = converter.F32StereoToS16Mono(srcDesc, dstDesc); + EXPECT_EQ(result, -1); +} + +// Test zero-length buffers +HWTEST_F(FormatConverterUnitTest, F32StereoToS16Mono_ZeroLengthBuffer, TestSize.Level1) +{ + FormatConverter converter; + + std::vector stereoData(4); + std::vector monoData(2); + + // Test zero-length source buffer + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), 0); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(int16_t)); + + int32_t result = converter.F32StereoToS16Mono(srcDesc, dstDesc); + EXPECT_EQ(result, -1); + + // Test zero-length destination buffer + srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + dstDesc = CreateBufferDesc(monoData.data(), 0); + + result = converter.F32StereoToS16Mono(srcDesc, dstDesc); + EXPECT_EQ(result, -1); +} + +// Test buffer length mismatch +HWTEST_F(FormatConverterUnitTest, F32StereoToS16Mono_BufferLengthMismatch, TestSize.Level1) +{ + FormatConverter converter; + + // Stereo data has 4 float samples (2 frames), but destination buffer can only hold 1 int16 sample + std::vector stereoData = {1.0f, 2.0f, 3.0f, 4.0f}; + std::vector monoData(1); // Too small, should need 2 int16 samples + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(int16_t)); + + int32_t result = converter.F32StereoToS16Mono(srcDesc, dstDesc); + EXPECT_EQ(result, -1); +} + +// Test edge case: single frame conversion +HWTEST_F(FormatConverterUnitTest, F32StereoToS16Mono_SingleFrame, TestSize.Level1) +{ + FormatConverter converter; + + std::vector stereoData = {1.0f, 0.0f}; // One stereo frame + std::vector monoData(1); + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(int16_t)); + + int32_t result = converter.F32StereoToS16Mono(srcDesc, dstDesc); + + EXPECT_EQ(result, 0); + EXPECT_EQ(monoData[0], static_cast(0.5f * 32767)); // (1.0+0.0)/2 = 0.5 → 0.5 * 32767 +} + +// Test full scale values +HWTEST_F(FormatConverterUnitTest, F32StereoToS16Mono_FullScaleValues, TestSize.Level1) +{ + FormatConverter converter; + + // Test maximum positive and negative values + std::vector stereoData = {1.0f, 1.0f, -1.0f, -1.0f}; // Two stereo frames + std::vector monoData(2); + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(int16_t)); + + int32_t result = converter.F32StereoToS16Mono(srcDesc, dstDesc); + + EXPECT_EQ(result, 0); + EXPECT_EQ(monoData[0], 32767); // (1.0+1.0)/2 = 1.0 → 32767 + EXPECT_EQ(monoData[1], -32768); // (-1.0+-1.0)/2 = -1.0 → -32768 +} + +// Test clipping behavior (values beyond ±1.0) +HWTEST_F(FormatConverterUnitTest, F32StereoToS16Mono_ClippingBehavior, TestSize.Level1) +{ + FormatConverter converter; + + // Test values that would exceed int16 range without clamping + std::vector stereoData = {2.0f, 2.0f, -2.0f, -2.0f}; // Values beyond ±1.0 + std::vector monoData(2); + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(int16_t)); + + int32_t result = converter.F32StereoToS16Mono(srcDesc, dstDesc); + + EXPECT_EQ(result, 0); + // Assuming CapMax() clamps values to ±1.0 range + EXPECT_EQ(monoData[0], 32767); // Clamped to (1.0+1.0)/2 = 1.0 → 32767 + EXPECT_EQ(monoData[1], -32768); // Clamped to (-1.0+-1.0)/2 = -1.0 → -32768 +} + +// Test multiple frames with various values +HWTEST_F(FormatConverterUnitTest, F32StereoToS16Mono_MultipleFrames, TestSize.Level1) +{ + FormatConverter converter; + + const size_t frameCount = 5; + std::vector stereoData(frameCount * 2); + std::vector monoData(frameCount); + + // Fill with various test values + stereoData = { + 0.25f, 0.75f, // → 0.5f + 0.1f, 0.9f, // → 0.5f + -0.3f, 0.3f, // → 0.0f + 0.9f, -0.9f, // → 0.0f + 0.0f, 0.0f // → 0.0f + }; + + BufferDesc srcDesc = CreateBufferDesc(stereoData.data(), stereoData.size() * sizeof(float)); + BufferDesc dstDesc = CreateBufferDesc(monoData.data(), monoData.size() * sizeof(int16_t)); + + int32_t result = converter.F32StereoToS16Mono(srcDesc, dstDesc); + + EXPECT_EQ(result, 0); + + // Verify conversion results + EXPECT_EQ(monoData[0], static_cast(0.5f * 32767)); // (0.25+0.75)/2 = 0.5 + EXPECT_EQ(monoData[1], static_cast(0.5f * 32767)); // (0.1+0.9)/2 = 0.5 + EXPECT_EQ(monoData[2], 0); // (-0.3+0.3)/2 = 0.0 + EXPECT_EQ(monoData[3], 0); // (0.9+-0.9)/2 = 0.0 + EXPECT_EQ(monoData[4], 0); // (0.0+0.0)/2 = 0.0 +} } // namespace OHOS::AudioStandard } // namespace OHOS diff --git a/services/audio_service/test/unittest/renderer_in_server_unit_test/BUILD.gn b/services/audio_service/test/unittest/renderer_in_server_unit_test/BUILD.gn index 8377ecef1f..cff24134fc 100644 --- a/services/audio_service/test/unittest/renderer_in_server_unit_test/BUILD.gn +++ b/services/audio_service/test/unittest/renderer_in_server_unit_test/BUILD.gn @@ -62,6 +62,7 @@ ohos_unittest("renderer_in_server_unit_test") { "../../../../../frameworks/native/audiopolicy/include", "../../../../../frameworks/native/audioclock/include", "../../../../audio_engine/manager/include", + "../../../../audio_engine/plugin/resample/include", ] configs = [ ":module_private_config" ] @@ -152,6 +153,7 @@ ohos_unittest("renderer_in_server_second_unit_test") { "../../../../../frameworks/native/audioclock/include", "../../../../../services/audio_engine/manager/include", "../../../../../services/audio_engine/buffer", + "../../../../../services/audio_engine/plugin/resample/include", ] configs = [ ":module_private_config" ] @@ -210,6 +212,7 @@ ohos_unittest("renderer_in_server_third_unit_test") { "../../../../../frameworks/native/audiopolicy/include", "../../../../../frameworks/native/audioclock/include", "../../../../../services/audio_engine/manager/include", + "../../../../../services/audio_engine/plugin/resample/include", ] configs = [ ":module_private_config" ] diff --git a/test/fuzztest/audioservice_fuzzer/audio_service_fuzzer.cpp b/test/fuzztest/audioservice_fuzzer/audio_service_fuzzer.cpp index 6eb259c634..8d74bf9b0a 100644 --- a/test/fuzztest/audioservice_fuzzer/audio_service_fuzzer.cpp +++ b/test/fuzztest/audioservice_fuzzer/audio_service_fuzzer.cpp @@ -378,7 +378,7 @@ void AudioServiceGetReleaseDelayTimeFuzzTest() AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared( static_cast(GetData() % ENDPOINTTYPESIZE), - GetData(), clientConfig); + GetData(), clientConfig.audioMode); endpoint->deviceInfo_.deviceType_ = g_testDeviceTypes[GetData() % g_testDeviceTypes.size()]; bool isSwitchStream = GetData(); bool isRecord = GetData(); @@ -598,7 +598,7 @@ void AudioServiceCheckDisableFastInnerFuzzTest() AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_VOIP_MMAP, - GetData(), clientConfig); + GetData(), clientConfig.audioMode); audioService->CheckDisableFastInner(endpoint); } @@ -619,7 +619,7 @@ void AudioServiceFilterAllFastProcessFuzzTest() sptr audioprocess = AudioProcessInServer::Create(config, audioService.get()); AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_VOIP_MMAP, - GetData(), clientConfig); + GetData(), clientConfig.audioMode); endpoint->deviceInfo_.deviceRole_ = g_testDeviceTypes[GetData() % g_testDeviceTypes.size()]; audioService->linkedPairedList_.clear(); audioService->linkedPairedList_.push_back(std::make_pair(audioprocess, endpoint)); @@ -643,7 +643,7 @@ void AudioServiceHandleFastCaptureFuzzTest() AudioProcessConfig clientConfig = {}; std::shared_ptr endpoint = std::make_shared(AudioEndpoint::TYPE_VOIP_MMAP, - GetData(), clientConfig); + GetData(), clientConfig.audioMode); audioService->HandleFastCapture(captureIds, audioprocess, endpoint); } @@ -764,7 +764,7 @@ void AudioServiceDumpFuzzTest() audioService->workingConfigs_.insert(make_pair(GetData(), playbackCaptureConfig)); config.audioMode = static_cast(GetData() % NUM_2); std::shared_ptr endpointInner = std::make_shared( - AudioEndpoint::TYPE_VOIP_MMAP, GetData(), config); + AudioEndpoint::TYPE_VOIP_MMAP, GetData(), config.audioMode); audioService->linkedPairedList_.clear(); audioService->linkedPairedList_.push_back(std::make_pair(audioProcess, endpointInner)); audioService->endpointList_.clear(); -- Gitee