diff --git a/frameworks/native/pulseaudio/src/modules/hdi/BUILD.gn b/frameworks/native/pulseaudio/src/modules/hdi/BUILD.gn index 53bc24b8..685a8f3d 100644 --- a/frameworks/native/pulseaudio/src/modules/hdi/BUILD.gn +++ b/frameworks/native/pulseaudio/src/modules/hdi/BUILD.gn @@ -51,7 +51,6 @@ ohos_shared_library("module-hdi-sink") { configs = [ ":hdi_config" ] cflags = [ "-DPA_MODULE_NAME=libmodule_hdi_sink_z_so" ] - cflags += [ "-DTEST_MODE" ] ldflags = [ "-Wl", diff --git a/frameworks/native/pulseaudio/src/modules/hdi/hdi_sink.c b/frameworks/native/pulseaudio/src/modules/hdi/hdi_sink.c index 6b47a3c9..0a02d945 100644 --- a/frameworks/native/pulseaudio/src/modules/hdi/hdi_sink.c +++ b/frameworks/native/pulseaudio/src/modules/hdi/hdi_sink.c @@ -79,10 +79,9 @@ struct Userdata { struct RendererSinkAdapter *sinkAdapter; pa_asyncmsgq *dq; pa_atomic_t dflag; -#ifdef TEST_MODE + bool test_mode_on; uint32_t writeCount; uint32_t renderCount; -#endif // TEST_MODE }; static void UserdataFree(struct Userdata *u); @@ -101,12 +100,53 @@ static ssize_t RenderWrite(struct Userdata *u, pa_memchunk *pchunk) p = pa_memblock_acquire(pchunk->memblock); pa_assert(p); -#ifdef TEST_MODE + while (true) { + uint64_t writeLen = 0; + + int32_t ret = u->sinkAdapter->RendererRenderFrame((char *)p + index, (uint64_t)length, &writeLen); + if (writeLen > length) { + AUDIO_ERR_LOG("Error writeLen > actual bytes. Length: %zu, Written: %" PRIu64 " bytes, %d ret", + length, writeLen, ret); + count = -1 - count; + break; + } + if (writeLen == 0) { + AUDIO_ERR_LOG("Failed to render Length: %zu, Written: %" PRIu64 " bytes, %d ret", + length, writeLen, ret); + count = -1 - count; + break; + } else { + count += writeLen; + index += writeLen; + length -= writeLen; + if (length <= 0) { + break; + } + } + } + pa_memblock_release(pchunk->memblock); + pa_memblock_unref(pchunk->memblock); + + return count; +} + +static ssize_t TestModeRenderWrite(struct Userdata *u, pa_memchunk *pchunk) +{ + size_t index, length; + ssize_t count = 0; + void *p = NULL; + + pa_assert(pchunk); + + index = pchunk->index; + length = pchunk->length; + p = pa_memblock_acquire(pchunk->memblock); + pa_assert(p); + if (*((int*)p) > 0) { AUDIO_DEBUG_LOG("RenderWrite Write: %{public}d", ++u->writeCount); } AUDIO_DEBUG_LOG("RenderWrite Write renderCount: %{public}d", ++u->renderCount); -#endif // TEST_MODE while (true) { uint64_t writeLen = 0; @@ -255,6 +295,40 @@ static void ThreadFuncWriteHDI(void *userdata) pa_asyncmsgq_done(u->dq, 0); } while (!quit); } + +static void TestModeThreadFuncWriteHDI(void *userdata) +{ + struct Userdata *u = userdata; + pa_assert(u); + + int quit = 0; + + do { + int code = 0; + pa_memchunk chunk; + + pa_assert_se(pa_asyncmsgq_get(u->dq, NULL, &code, NULL, NULL, &chunk, 1) == 0); + + switch (code) { + case HDI_RENDER: + if (TestModeRenderWrite(u, &chunk) < 0) { + u->bytes_dropped += chunk.length; + AUDIO_ERR_LOG("TestModeRenderWrite failed"); + } + if (pa_atomic_load(&u->dflag) == 1) { + pa_atomic_sub(&u->dflag, 1); + } + break; + case QUIT: + quit = 1; + break; + default: + break; + } + pa_asyncmsgq_done(u->dq, 0); + } while (!quit); +} + static void SinkUpdateRequestedLatencyCb(pa_sink *s) { struct Userdata *u = NULL; @@ -341,10 +415,8 @@ static int SinkSetStateInIoThreadCb(pa_sink *s, pa_sink_state_t newState, pa_core_exit(u->core, true, 0); } else { u->isHDISinkStarted = true; -#ifdef TEST_MODE u->writeCount = 0; u->renderCount = 0; -#endif // TEST_MODE AUDIO_INFO_LOG("Successfully restarted HDI renderer"); } } else if (PA_SINK_IS_OPENED(s->thread_info.state)) { @@ -520,12 +592,13 @@ pa_sink *PaHdiSinkNew(pa_module *m, pa_modargs *ma, const char *driver) goto fail; } + u->test_mode_on = false; + if (pa_modargs_get_value_boolean(ma, "test_mode_on", &u->test_mode_on) < 0) { + AUDIO_INFO_LOG("No test_mode_on arg. Normal mode it is."); + } + pa_atomic_store(&u->dflag, 0); u->dq = pa_asyncmsgq_new(0); -#ifdef TEST_MODE - u->writeCount = 0; - u->renderCount = 0; -#endif // TEST_MODE u->sink = PaHdiSinkInit(u, ma, driver); if (!u->sink) { @@ -566,10 +639,20 @@ pa_sink *PaHdiSinkNew(pa_module *m, pa_modargs *ma, const char *driver) goto fail; } - hdiThreadName = "write-hdi"; - if (!(u->thread_hdi = pa_thread_new(hdiThreadName, ThreadFuncWriteHDI, u))) { - AUDIO_ERR_LOG("Failed to write-hdi thread."); - goto fail; + if (u->test_mode_on) { + u->writeCount = 0; + u->renderCount = 0; + hdiThreadName = "test-mode-write-hdi"; + if (!(u->thread_hdi = pa_thread_new(hdiThreadName, TestModeThreadFuncWriteHDI, u))) { + AUDIO_ERR_LOG("Failed to test-mode-write-hdi thread."); + goto fail; + } + } else { + hdiThreadName = "write-hdi"; + if (!(u->thread_hdi = pa_thread_new(hdiThreadName, ThreadFuncWriteHDI, u))) { + AUDIO_ERR_LOG("Failed to write-hdi thread."); + goto fail; + } } pa_sink_put(u->sink); diff --git a/frameworks/native/pulseaudio/src/modules/hdi/module_hdi_sink.c b/frameworks/native/pulseaudio/src/modules/hdi/module_hdi_sink.c index f6f5c62a..7743f999 100644 --- a/frameworks/native/pulseaudio/src/modules/hdi/module_hdi_sink.c +++ b/frameworks/native/pulseaudio/src/modules/hdi/module_hdi_sink.c @@ -43,6 +43,7 @@ PA_MODULE_USAGE( "sink_latency=" "render_in_idle_state" "open_mic_speaker" + "test_mode_on" ); static const char * const VALID_MODARGS[] = { @@ -60,6 +61,7 @@ static const char * const VALID_MODARGS[] = { "sink_latency", "render_in_idle_state", "open_mic_speaker", + "test_mode_on", NULL }; diff --git a/services/BUILD.gn b/services/BUILD.gn index 2e800004..29358b1f 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn @@ -91,6 +91,7 @@ ohos_prebuilt_etc("audio_policy.rc") { config("audio_policy_public_config") { include_dirs = [ + "//base/startup/syspara_lite/interfaces/innerkits/native/syspara/include", "//drivers/peripheral/audio/interfaces/include", "//foundation/multimedia/audio_framework/services/include", "//foundation/multimedia/audio_framework/services/include/audio_service/client", @@ -190,6 +191,7 @@ ohos_shared_library("audio_policy_service") { "$hdf_uhdf_path/host:libhdf_host", "$hdf_uhdf_path/ipc:libhdf_ipc_adapter", "$hdf_uhdf_path/utils:libhdf_utils", + "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", "//foundation/communication/bluetooth/services/bluetooth/ipc:btipc_static", "//foundation/communication/ipc/interfaces/innerkits/ipc_core:ipc_core", "//foundation/distributeddatamgr/distributeddatamgr/interfaces/innerkits/distributeddata:distributeddata_inner", diff --git a/services/include/audio_policy/server/service/manager/audio_adapter_manager.h b/services/include/audio_policy/server/service/manager/audio_adapter_manager.h index fee77033..98fc891c 100644 --- a/services/include/audio_policy/server/service/manager/audio_adapter_manager.h +++ b/services/include/audio_policy/server/service/manager/audio_adapter_manager.h @@ -129,6 +129,7 @@ private: AudioSessionCallback *sessionCallback_; friend class PolicyCallbackImpl; + bool testModeOn_ {false}; }; class PolicyCallbackImpl : public AudioServiceAdapterCallback { diff --git a/services/src/audio_policy/server/service/manager/audio_adapter_manager.cpp b/services/src/audio_policy/server/service/manager/audio_adapter_manager.cpp index 3af4c3de..234feca0 100644 --- a/services/src/audio_policy/server/service/manager/audio_adapter_manager.cpp +++ b/services/src/audio_policy/server/service/manager/audio_adapter_manager.cpp @@ -18,6 +18,7 @@ #include "audio_errors.h" #include "audio_log.h" +#include "parameter.h" #include "audio_adapter_manager.h" @@ -27,6 +28,13 @@ namespace OHOS { namespace AudioStandard { bool AudioAdapterManager::Init() { + char testMode[10] = {0}; // 10 for system parameter usage + auto res = GetParameter("debug.audio_service.testmodeon", "0", testMode, sizeof(testMode)); + if (res == 1 && testMode[0] == '1') { + AUDIO_DEBUG_LOG("testMode on"); + testModeOn_ = true; + } + return true; } @@ -306,6 +314,10 @@ std::string AudioAdapterManager::GetModuleArgs(const AudioModuleInfo &audioModul args.append(" sink_latency="); args.append(audioModuleInfo.sinkLatency); } + if (testModeOn_) { + args.append(" test_mode_on="); + args.append("1"); + } } else if (audioModuleInfo.lib == HDI_SOURCE) { UpdateCommonArgs(audioModuleInfo, args); if (!audioModuleInfo.name.empty()) { diff --git a/services/src/audio_service/client/audio_service_client.cpp b/services/src/audio_service/client/audio_service_client.cpp index 2555059f..844e6b97 100644 --- a/services/src/audio_service/client/audio_service_client.cpp +++ b/services/src/audio_service/client/audio_service_client.cpp @@ -1479,14 +1479,12 @@ int32_t AudioServiceClient::RenderPrebuf(uint32_t writeLen) int32_t writeError; StreamBuffer prebufStream; prebufStream.buffer = preBuf_.get(); - uint32_t extra {0}; if (writeLen == 0) { return AUDIO_CLIENT_SUCCESS; } else if (writeLen > diff) { prebufStream.bufferLen = diff; } else { prebufStream.bufferLen = writeLen; - extra = diff % writeLen; } size_t bytesWritten {0}; @@ -1497,12 +1495,12 @@ int32_t AudioServiceClient::RenderPrebuf(uint32_t writeLen) return AUDIO_CLIENT_ERR; } - if ((diff - bytesWritten) <= 0) { + if (static_cast(diff - bytesWritten) <= 0) { break; } - if ((diff - bytesWritten) == extra) { - prebufStream.bufferLen = extra; + if ((diff - bytesWritten) < writeLen) { + prebufStream.bufferLen = diff - bytesWritten; } } diff --git a/services/src/audio_service/client/audio_stream.cpp b/services/src/audio_service/client/audio_stream.cpp index 9d26db35..e2437921 100644 --- a/services/src/audio_service/client/audio_stream.cpp +++ b/services/src/audio_service/client/audio_stream.cpp @@ -434,14 +434,12 @@ size_t AudioStream::Write(uint8_t *buffer, size_t buffer_size) stream.bufferLen = buffer_size; isWriteInProgress_ = true; -#ifdef LATENCY_ACCURACY_TEST if (isFirstWrite_) { if (RenderPrebuf(stream.bufferLen)) { return ERR_WRITE_FAILED; } isFirstWrite_ = false; } -#endif // LATENCY_ACCURACY_TEST size_t bytesWritten = WriteStream(stream, writeError); isWriteInProgress_ = false; diff --git a/services/test/audio_renderer_test.cpp b/services/test/audio_renderer_test.cpp index e9b74f4f..8473651e 100644 --- a/services/test/audio_renderer_test.cpp +++ b/services/test/audio_renderer_test.cpp @@ -254,7 +254,7 @@ public: if (audioRenderer->GetLatency(latency)) { AUDIO_ERR_LOG("AudioRendererTest: GetLatency failed"); break; -#if LATENCY_ACCURACY_TEST +#ifdef LATENCY_ACCURACY_TEST } else { AUDIO_DEBUG_LOG("GetLatency: %{public}" PRIu64, latency); #endif // LATENCY_ACCURACY_TEST