/*---------------------------------------------------------------------------- * Copyright (c) TJD Technologies Co., Ltd. 2025. All rights reserved. * * Description: TjdPhoneAudio.cpp * * Author: luziquan@ss-tjd.com * * Create: 2025-08-16 *--------------------------------------------------------------------------*/ #include "TjdPhoneAudio.h" #include "TjdPhoneService.h" #include "audio_errors.h" #include "sys_config.h" #define ENABLE_PRINT_INFO 1 #if ENABLE_PRINT_INFO #define static_print_warn(...) sys_phone_log_w(__VA_ARGS__) // 警告信息打印一般常开 #define static_print_error(...) sys_phone_log_e(__VA_ARGS__) // 错误信息打印一般常开 #define static_print_debug(...) sys_phone_log_d(__VA_ARGS__) // 调试信息打印一般常开 #else #define static_print_warn(...) #define static_print_error(...) #define static_print_debug(...) #endif class PhoneAudioInterruptListener : public Audio::InterruptListener { public: PhoneAudioInterruptListener() {}; ~PhoneAudioInterruptListener() {}; void OnInterrupt(int32_t type, int32_t hint) override { UNUSED(type); UNUSED(hint); static_print_debug("[PhoneAudioInterruptListener] OnInterrupt: type = %d, hint = %d", type, hint); } }; static std::shared_ptr g_audioIntListener = nullptr; int32_t TjdPhoneAudio::AudioInit(void) { bool ret = amInstance_.Initialize(); if (!ret) { static_print_error("[%s] line:%d, audio manager init failed", __FUNCTION__, __LINE__); return AUDIO_ERROR; } static_print_error("[%s] line:%d, success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioGetMinVolume(void) { return amInstance_.GetMinVolume(AUDIO_STREAM_VOICE_CALL_BT_SCO); } int32_t TjdPhoneAudio::PhoneAudioGetMaxVolume(void) { return amInstance_.GetMaxVolume(AUDIO_STREAM_VOICE_CALL_BT_SCO); } int32_t TjdPhoneAudio::PhoneAudioGetVolume(void) { return amInstance_.GetVolume(AUDIO_STREAM_VOICE_CALL_BT_SCO); } bool TjdPhoneAudio::PhoneAudioSetVolume(int32_t volume) { return amInstance_.SetVolume(AUDIO_STREAM_VOICE_CALL_BT_SCO, volume); } // 设置通话speaker静音/取消静音 bool TjdPhoneAudio::PhoneAudioSetSpeakerMute(bool isMute) { bool ret; static_print_debug("[PhoneAudioSetSpeakerMute] start"); ret = amInstance_.IsMute(AUDIO_STREAM_VOICE_CALL_BT_SCO); if (ret == isMute) { return true; } if (isMute) { ret = amInstance_.Mute(AUDIO_STREAM_VOICE_CALL_BT_SCO); } else { ret = amInstance_.UnMute(AUDIO_STREAM_VOICE_CALL_BT_SCO); } static_print_debug("[PhoneAudioSetSpeakerMute] end! ret = %d", ret); return ret; } // 设置通话mic静音/取消静音 bool TjdPhoneAudio::PhoneAudioSetMicMute(bool isMute) { bool ret; static_print_debug("[PhoneAudioSetMicMute] start"); ret = amInstance_.IsMicrophoneMute(); if (ret == isMute) { return true; } ret = amInstance_.SetMicrophoneMute(isMute); static_print_debug("[PhoneAudioSetMicMute] end! ret = %d", ret); return ret; } static bool CheckParam(int32_t instanceNum) { if (instanceNum == 0 || instanceNum == 1) { return true; } return false; } int32_t TjdPhoneAudio::PhoneAudioManagerActInterrupt(AudioStreamType streamType) { /* request audio focus */ static_print_debug("[%s] streamType:0x%x", __FUNCTION__, streamType); sessionId_ = amInstance_.MakeSessionId(); if (sessionId_ == AUDIO_SESSION_ID_NONE) { static_print_error("[%s] line:%d, make session id failed", __FUNCTION__, __LINE__); return AUDIO_ERROR; } static_print_debug("[%s] line:%d, session id = %d", __FUNCTION__, __LINE__, sessionId_); g_audioIntListener = std::make_shared(); if (g_audioIntListener.get() == nullptr) { static_print_error("[%s] line:%d, g_audioIntListener is null", __FUNCTION__, __LINE__); return AUDIO_ERROR; } interrupt_ = {streamType, sessionId_, g_audioIntListener}; if (amInstance_.ActivateAudioInterrupt(interrupt_) == INTERRUPT_FAILED) { static_print_error("[%s] line:%d, ActivateAudioInterrupt failed", __FUNCTION__, __LINE__); return AUDIO_ERROR; } static_print_debug("[%s] line:%d, success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioManagerSetDeviceConnState(AudioDeviceType deviceType, AudioDeviceConnectState connectState) { int32_t ret = amInstance_.SetDeviceConnectionState(deviceType, connectState); if (ret != AUDIO_SUCCESS) { static_print_error("[%s] line:%d failed, deviceType = 0x%x connectState = %d ret = %d", __FUNCTION__, __LINE__, deviceType, connectState, ret); return AUDIO_ERROR; } static_print_debug("[%s] line:%d success, deviceType = 0x%x connectState = %d", __FUNCTION__, __LINE__, deviceType, connectState); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioStreamInInit(AudioLinkDirection linkDir) { int32_t instanceNum = INVALID_AUDIO_VALUE; static_print_debug("[%s] linkDir:0x%x", __FUNCTION__, linkDir); /* create ASI instance UP_LINK: index 0, DOWN_LINK: index 1 */ if (linkDir == AUDIO_UP_LINK) { g_streamIn[0] = std::make_shared(); instanceNum = 0; } else if (linkDir == AUDIO_DOWN_LINK) { g_streamIn[1] = std::make_shared(); instanceNum = 1; } else { static_print_error("[%s] line:%d failed, invalid linkDir = %d", __FUNCTION__, __LINE__, linkDir); return AUDIO_ERROR; } if (g_streamIn[instanceNum] == nullptr || g_streamIn[instanceNum].get() == nullptr) { static_print_error("[%s] line:%d make_shared AudioStreamIn failed", __FUNCTION__, __LINE__); return AUDIO_ERROR; } /* init ASI */ CapturerInputConfig captureConfig = { .streamType = AUDIO_STREAM_VOICE_CALL_BT_SCO, .sessionID = sessionId_, .channelCount = AUDIO_CHANNEL_1, .linkDir = linkDir, }; captureConfig.audioFormat = (AudioCodecFormat)GetCallAudioCodec(); if (captureConfig.audioFormat == PCM) { captureConfig.sampleRate = AUDIO_SAMPLE_RATE_8K; } else if (captureConfig.audioFormat == mSBC) { captureConfig.sampleRate = AUDIO_SAMPLE_RATE_16K; } int32_t ret = g_streamIn[instanceNum]->Init(captureConfig); if (ret != AUDIO_SUCCESS) { static_print_error("[%s] line:%d streamIn init failed, ret: 0x%x", __FUNCTION__, __LINE__, ret); return AUDIO_ERROR; } static_print_debug("[%s] line:%d success, instanceNum = %d", __FUNCTION__, __LINE__, instanceNum); return instanceNum; } int32_t TjdPhoneAudio::PhoneAudioStreamOutInit(AudioLinkDirection linkDir) { int32_t instanceNum = INVALID_AUDIO_VALUE; static_print_debug("[%s] linkDir:0x%x", __FUNCTION__, linkDir); /* create ASO instance UP_LINK: index 0, DOWN_LINK: index 1 */ if (linkDir == AUDIO_UP_LINK) { g_streamOut[0] = std::make_shared(); instanceNum = 0; } else if (linkDir == AUDIO_DOWN_LINK) { g_streamOut[1] = std::make_shared(); instanceNum = 1; } else { static_print_error("[%s] line:%d failed, invalid linkDir = %d", __FUNCTION__, __LINE__, linkDir); return AUDIO_ERROR; } if (g_streamOut[instanceNum] == nullptr || g_streamOut[instanceNum].get() == nullptr) { static_print_error("[%s] line:%d make_shared AudioStreamOut failed", __FUNCTION__, __LINE__); return AUDIO_ERROR; } /* init ASO */ AudioRendererConfig renderConfig = { .streamType = AUDIO_STREAM_VOICE_CALL_BT_SCO, .sessionID = sessionId_, .channelCount = AUDIO_CHANNEL_1, .linkDir = linkDir, }; renderConfig.audioFormat = (AudioCodecFormat)GetCallAudioCodec(); if (renderConfig.audioFormat == PCM) { renderConfig.sampleRate = AUDIO_SAMPLE_RATE_8K; } else if (renderConfig.audioFormat == mSBC) { renderConfig.sampleRate = AUDIO_SAMPLE_RATE_16K; } int32_t ret = g_streamOut[instanceNum]->Init(renderConfig); if (ret != AUDIO_SUCCESS) { static_print_error("[%s] line:%d streamOut init failed, ret: 0x%x", __FUNCTION__, __LINE__, ret); return AUDIO_ERROR; } /* dump stream */ g_streamOut[instanceNum]->DumpInfo(); static_print_debug("[%s] line:%d success, instanceNum = %d", __FUNCTION__, __LINE__, instanceNum); return instanceNum; } int32_t TjdPhoneAudio::PhoneAudioStreamInStart(int32_t instanceNum) { static_print_debug("[%s] instanceNum:0x%x", __FUNCTION__, instanceNum); bool isValid = CheckParam(instanceNum); if (!isValid) { static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum); return AUDIO_ERROR; } /* start ASI */ int32_t ret = g_streamIn[instanceNum]->Start(); if (ret != AUDIO_SUCCESS) { static_print_error("[%s] line:%d streamIn Start failed ret: 0x%x", __FUNCTION__, __LINE__, ret); return AUDIO_ERROR; } static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioStreamOutStart(int32_t instanceNum) { static_print_debug("[%s] instanceNum:0x%x", __FUNCTION__, instanceNum); bool isValid = CheckParam(instanceNum); if (!isValid) { static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum); return AUDIO_ERROR; } /* start ASO */ int32_t ret = g_streamOut[instanceNum]->Play(); if (ret != AUDIO_SUCCESS) { static_print_error("[%s] line:%d streamOut Play failed ret: 0x%x", __FUNCTION__, __LINE__, ret); return AUDIO_ERROR; } static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioStreamInGetChannelId(int32_t instanceNum, uint32_t *shmId) { bool isValid = CheckParam(instanceNum); if (!isValid || shmId == nullptr) { static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum); return AUDIO_ERROR; } /* obtain ASI channel id(adp handle) */ uint32_t channelId; int32_t ret = g_streamIn[instanceNum]->GetCurrentChannelId(channelId); if (ret != AUDIO_SUCCESS) { static_print_error("[%s] line:%d streamIn get Id failed ret: 0x%x", __FUNCTION__, __LINE__, ret); return AUDIO_ERROR; } static_print_debug("[%s] line:%d stream in channelId: 0x%x", __FUNCTION__, __LINE__, channelId); *shmId = channelId; static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioStreamOutGetChannelId(int32_t instanceNum, uint32_t *shmId) { bool isValid = CheckParam(instanceNum); if (!isValid || shmId == nullptr) { static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum); return AUDIO_ERROR; } /* obtain ASO channel id(adp handle) */ uint32_t channelId; int32_t ret = g_streamOut[instanceNum]->GetCurrentChannelId(channelId); if (ret != AUDIO_SUCCESS) { static_print_error("[%s] line:%d streamOut get Id failed ret: 0x%x", __FUNCTION__, __LINE__, ret); return AUDIO_ERROR; } static_print_debug("[%s] line:%d stream out channelId: 0x%x", __FUNCTION__, __LINE__, channelId); *shmId = channelId; static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioStreamInAttachBackend(int32_t instanceNum, uint32_t backendId) { bool isValid = CheckParam(instanceNum); if (!isValid) { static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum); return AUDIO_ERROR; } /* ASI set shm id */ int32_t ret = g_streamIn[instanceNum]->AttachBackend(backendId); if (ret != AUDIO_SUCCESS) { static_print_error("[%s] line:%d streamIn AttachBackend failed backendId: 0x%x, ret: 0x%x", __FUNCTION__, __LINE__, backendId, ret); return AUDIO_ERROR; } static_print_debug("[%s] line:%d, stream in instanceNum: %d, backendId: 0x%x", __FUNCTION__, __LINE__, instanceNum, backendId); static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioStreamOutAttachFrontend(int32_t instanceNum, uint32_t frontendId) { bool isValid = CheckParam(instanceNum); if (!isValid) { static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum); return AUDIO_ERROR; } /* ASO set shm id */ int32_t ret = g_streamOut[instanceNum]->AttachFrontend(frontendId); if (ret != AUDIO_SUCCESS) { static_print_error("[%s] line:%d streamOut AttachFrontend failed frontendId: 0x%x, ret: 0x%x", __FUNCTION__, __LINE__, frontendId, ret); return AUDIO_ERROR; } static_print_debug("[%s] line:%d, stream out instanceNum: %d, frontendId: 0x%x", __FUNCTION__, __LINE__, instanceNum, frontendId); static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioStreamInStop(int32_t instanceNum) { bool isValid = CheckParam(instanceNum); if (!isValid) { static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum); return AUDIO_ERROR; } /* stop ASI */ int32_t ret = g_streamIn[instanceNum]->Stop(); if (ret != AUDIO_SUCCESS) { static_print_error("[%s] line:%d streamIn Stop failed ret: 0x%x", __FUNCTION__, __LINE__, ret); } static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioStreamOutStop(int32_t instanceNum) { bool isValid = CheckParam(instanceNum); if (!isValid) { static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum); return AUDIO_ERROR; } /* stop ASO */ int32_t ret = g_streamOut[instanceNum]->Stop(); if (ret != AUDIO_SUCCESS) { static_print_error("[%s] line:%d streamOut Stop failed ret: 0x%x", __FUNCTION__, __LINE__, ret); } static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioStreamInDeinit(int32_t instanceNum) { bool isValid = CheckParam(instanceNum); if (!isValid) { static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum); return AUDIO_ERROR; } /* deinit ASI */ if (g_streamIn[instanceNum] != nullptr) { g_streamIn[instanceNum]->Release(); g_streamIn[instanceNum] = nullptr; } static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioStreamOutDeinit(int32_t instanceNum) { bool isValid = CheckParam(instanceNum); if (!isValid) { static_print_error("[%s] line:%d instanceNum %d is invalid", __FUNCTION__, __LINE__, instanceNum); return AUDIO_ERROR; } /* deinit ASO */ if (g_streamOut[instanceNum] != nullptr) { g_streamOut[instanceNum]->Release(); g_streamOut[instanceNum] = nullptr; } static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; } int32_t TjdPhoneAudio::PhoneAudioManagerDeactInterrupt(void) { /* release audio focus */ int32_t ret = amInstance_.DeactivateAudioInterrupt(interrupt_); if (ret != AUDIO_SUCCESS) { static_print_error("[%s] line:%d DeactivateAudioInterrupt failed ret = %d", __FUNCTION__, __LINE__, ret); return AUDIO_ERROR; } static_print_debug("[%s] line:%d success", __FUNCTION__, __LINE__); return AUDIO_SUCCESS; }