status_t LoopbackManager::SetLoopbackOn(loopback_t loopback_type, loopback_output_device_t loopback_output_device) { Mutex::Autolock _l(mLock); ALOGD("+%s(), loopback_type = %d, loopback_output_device = %d", __FUNCTION__, loopback_type, loopback_output_device); if (mLoopbackType != NO_LOOPBACK) { // check no loobpack function on ALOGD("-%s() : Please Turn off Loopback Type %d First!!", __FUNCTION__, mLoopbackType); return ALREADY_EXISTS; } else if (CheckLoopbackTypeIsValid(loopback_type) != NO_ERROR) { // to avoid using undefined loopback type & ref/dual mic in single mic project ALOGW("-%s(): No such Loopback type %d", __FUNCTION__, loopback_type); return BAD_TYPE; } // lock AudioResourceManagerInterface *pAudioResourceManager = AudioResourceManagerFactory::CreateAudioResource(); pAudioResourceManager->EnableAudioLock(AudioResourceManagerInterface::AUDIO_HARDWARE_LOCK, 3000); pAudioResourceManager->EnableAudioLock(AudioResourceManagerInterface::AUDIO_MODE_LOCK, 3000); pAudioResourceManager->EnableAudioLock(AudioResourceManagerInterface::AUDIO_VOLUME_LOCK, 3000); // force all input/output streams standby AudioMTKStreamManager::getInstance()->ForceAllStandby(); // copy current device mInputDeviceCopy = (audio_devices_t)pAudioResourceManager->getUlInputDevice(); mOutputDeviceCopy = (audio_devices_t)pAudioResourceManager->getDlOutputDevice(); // get loopback device audio_devices_t input_device = GetInputDeviceByLoopbackType(loopback_type); audio_devices_t output_device = GetOutputDeviceByLoopbackType(loopback_type, loopback_output_device); // check modem status SpeechDriverInterface *pSpeechDriver = SpeechDriverFactory::GetInstance()->GetSpeechDriverByIndex(mWorkingModemIndex); if (pSpeechDriver->CheckModemIsReady() == false) { // modem is sleep... for (int modem_index = MODEM_1; modem_index < NUM_MODEM; modem_index++) { // get working modem index pSpeechDriver = SpeechDriverFactory::GetInstance()->GetSpeechDriverByIndex((modem_index_t)modem_index); if (pSpeechDriver != NULL && pSpeechDriver->CheckModemIsReady() == true) { mWorkingModemIndex = (modem_index_t)modem_index; break; } } } // to avoid BT test being interferenced by modem side speech enhancement if (loopback_type == MD_BT_LOOPBACK) { SpeechDriverFactory::GetInstance()->GetSpeechDriverByIndex(mWorkingModemIndex)->SetSpeechEnhancement(false); } // to turn on/off DMNR if (loopback_type == MD_DUAL_MIC_ACOUSTIC_LOOPBACK_WITHOUT_DMNR || loopback_type == MD_DUAL_MIC_ACOUSTIC_LOOPBACK_WITH_DMNR) { mMaskCopy = SpeechEnhancementController::GetInstance()->GetSpeechEnhancementMask(); // copy DMNR mask sph_enh_mask_struct_t mask = mMaskCopy; if (loopback_type == MD_DUAL_MIC_ACOUSTIC_LOOPBACK_WITHOUT_DMNR) { mask.dynamic_func &= (~SPH_ENH_DYNAMIC_MASK_DMNR); } else if (loopback_type == MD_DUAL_MIC_ACOUSTIC_LOOPBACK_WITH_DMNR) { mask.dynamic_func |= SPH_ENH_DYNAMIC_MASK_DMNR; } SpeechDriverFactory::GetInstance()->GetSpeechDriverByIndex(mWorkingModemIndex)->SetSpeechEnhancementMask(mask); } // Enable loopback function switch (loopback_type) { case AP_MAIN_MIC_AFE_LOOPBACK: case AP_HEADSET_MIC_AFE_LOOPBACK: case AP_REF_MIC_AFE_LOOPBACK: case AP_BT_LOOPBACK: { AudioLoopbackController::GetInstance()->OpenAudioLoopbackControlFlow(input_device, output_device); break; } case MD_MAIN_MIC_ACOUSTIC_LOOPBACK: case MD_HEADSET_MIC_ACOUSTIC_LOOPBACK: case MD_DUAL_MIC_ACOUSTIC_LOOPBACK_WITHOUT_DMNR: case MD_DUAL_MIC_ACOUSTIC_LOOPBACK_WITH_DMNR: case MD_REF_MIC_ACOUSTIC_LOOPBACK: case MD_BT_LOOPBACK: { SpeechLoopbackController::GetInstance()->OpenModemLoopbackControlFlow(mWorkingModemIndex, input_device, output_device); break; } default: { ALOGW("%s(): Loopback type %d not implemented!!", __FUNCTION__, loopback_type); ASSERT(0); } } // only use L ch data, so mute R ch. (Disconnect ADC_I2S_IN_R -> MODEM_PCM_TX_R) if (loopback_type == MD_MAIN_MIC_ACOUSTIC_LOOPBACK || loopback_type == MD_REF_MIC_ACOUSTIC_LOOPBACK) { AudioDigitalControlFactory::CreateAudioDigitalControl()->SetinputConnection( AudioDigitalType::DisConnect, AudioDigitalType::I04, (mWorkingModemIndex == MODEM_1) ? AudioDigitalType::O18 : AudioDigitalType::O08); } // save opened loobpack type mLoopbackType = loopback_type; // acquire wake lock int ret = acquire_wake_lock(PARTIAL_WAKE_LOCK, LOOPBACK_WAKELOCK_NAME); ALOGD("%s(), acquire_wake_lock:%s, return %d.", __FUNCTION__, LOOPBACK_WAKELOCK_NAME, ret); // unlock pAudioResourceManager->DisableAudioLock(AudioResourceManagerInterface::AUDIO_VOLUME_LOCK); pAudioResourceManager->DisableAudioLock(AudioResourceManagerInterface::AUDIO_MODE_LOCK); pAudioResourceManager->DisableAudioLock(AudioResourceManagerInterface::AUDIO_HARDWARE_LOCK); ALOGD("-%s(), loopback_type = %d, loopback_output_device = %d", __FUNCTION__, loopback_type, loopback_output_device); return NO_ERROR; }
status_t LoopbackManager::SetLoopbackOn(loopback_t loopback_type, loopback_output_device_t loopback_output_device) { ALOGD("+%s(), loopback_type = %d, loopback_output_device = %d", __FUNCTION__, loopback_type, loopback_output_device); Mutex::Autolock _l(mLock); if (mLoopbackType != NO_LOOPBACK) // check no loobpack function on { ALOGD("-%s() : Please Turn off Loopback Type %d First!!", __FUNCTION__, mLoopbackType); return ALREADY_EXISTS; } else if (CheckLoopbackTypeIsValid(loopback_type) != NO_ERROR) // to avoid using undefined loopback type & ref/dual mic in single mic project { ALOGW("-%s(): No such Loopback type %d", __FUNCTION__, loopback_type); return BAD_TYPE; } // suspend & standby all input/output streams AudioALSAStreamManager::getInstance()->setAllStreamsSuspend(true); AudioALSAStreamManager::getInstance()->standbyAllStreams(); // copy current device // TODO(Harvey): recover device //mInputDeviceCopy = (audio_devices_t)pAudioResourceManager->getUlInputDevice(); //mOutputDeviceCopy = (audio_devices_t)pAudioResourceManager->getDlOutputDevice(); // get loopback device audio_devices_t input_device = GetInputDeviceByLoopbackType(loopback_type); audio_devices_t output_device = GetOutputDeviceByLoopbackType(loopback_type, loopback_output_device); // set specific mic type if (loopback_type == AP_MAIN_MIC_AFE_LOOPBACK || loopback_type == MD_MAIN_MIC_ACOUSTIC_LOOPBACK) { AudioALSAHardwareResourceManager::getInstance()->setBuiltInMicSpecificType(BUILTIN_MIC_MIC1_ONLY); } else if (loopback_type == AP_REF_MIC_AFE_LOOPBACK || loopback_type == MD_REF_MIC_ACOUSTIC_LOOPBACK) { AudioALSAHardwareResourceManager::getInstance()->setBuiltInMicSpecificType(BUILTIN_MIC_MIC2_ONLY); } else if (loopback_type == AP_3RD_MIC_AFE_LOOPBACK || loopback_type == MD_3RD_MIC_ACOUSTIC_LOOPBACK) { AudioALSAHardwareResourceManager::getInstance()->setBuiltInMicSpecificType(BUILTIN_MIC_MIC3_ONLY); } // check modem status if (CheckIsModemLoopback(loopback_type) == true) { SpeechDriverInterface *pSpeechDriver = SpeechDriverFactory::GetInstance()->GetSpeechDriverByIndex(mWorkingModemIndex); if (pSpeechDriver->CheckModemIsReady() == false) // modem is sleep... { for (int modem_index = MODEM_1; modem_index < NUM_MODEM; modem_index++) // get working modem index { pSpeechDriver = SpeechDriverFactory::GetInstance()->GetSpeechDriverByIndex((modem_index_t)modem_index); if (pSpeechDriver != NULL && pSpeechDriver->CheckModemIsReady() == true) { mWorkingModemIndex = (modem_index_t)modem_index; SpeechDriverFactory::GetInstance()->SetActiveModemIndex(mWorkingModemIndex); break; } } } } // to avoid BT test being interferenced by modem side speech enhancement mBtHeadsetNrecOnCopy = SpeechEnhancementController::GetInstance()->GetBtHeadsetNrecOn(); if (loopback_type == MD_BT_LOOPBACK || loopback_type == MD_BT_LOOPBACK_NO_CODEC) { SpeechEnhancementController::GetInstance()->SetBtHeadsetNrecOnToAllModem(false); } // to turn on/off DMNR if (loopback_type == MD_DUAL_MIC_ACOUSTIC_LOOPBACK_WITHOUT_DMNR || loopback_type == MD_DUAL_MIC_ACOUSTIC_LOOPBACK_WITH_DMNR) { mMaskCopy = SpeechEnhancementController::GetInstance()->GetSpeechEnhancementMask(); // copy DMNR mask sph_enh_mask_struct_t mask = mMaskCopy; if (loopback_type == MD_DUAL_MIC_ACOUSTIC_LOOPBACK_WITHOUT_DMNR) { mask.dynamic_func &= (~SPH_ENH_DYNAMIC_MASK_DMNR); } else if (loopback_type == MD_DUAL_MIC_ACOUSTIC_LOOPBACK_WITH_DMNR) { mask.dynamic_func |= SPH_ENH_DYNAMIC_MASK_DMNR; } SpeechDriverFactory::GetInstance()->GetSpeechDriverByIndex(mWorkingModemIndex)->SetSpeechEnhancementMask(mask); } // BT CVSD if (loopback_type == AP_BT_LOOPBACK) { AudioALSALoopbackController::getInstance()->SetApBTCodec(true); AudioALSALoopbackController::getInstance()->OpenAudioLoopbackControlFlow(input_device, output_device); } else if (loopback_type == AP_BT_LOOPBACK_NO_CODEC) { AudioALSALoopbackController::getInstance()->SetApBTCodec(false); AudioALSALoopbackController::getInstance()->OpenAudioLoopbackControlFlow(input_device, output_device); } else if (loopback_type == MD_BT_LOOPBACK) { AudioALSASpeechLoopbackController::getInstance()->SetModemBTCodec(true); AudioALSASpeechLoopbackController::getInstance()->OpenModemLoopbackControlFlow(input_device, output_device); } else if (loopback_type == MD_BT_LOOPBACK_NO_CODEC) { AudioALSASpeechLoopbackController::getInstance()->SetModemBTCodec(false); AudioALSASpeechLoopbackController::getInstance()->OpenModemLoopbackControlFlow(input_device, output_device); } else { // Enable loopback function switch (loopback_type) { case AP_MAIN_MIC_AFE_LOOPBACK: case AP_HEADSET_MIC_AFE_LOOPBACK: case AP_REF_MIC_AFE_LOOPBACK: case AP_3RD_MIC_AFE_LOOPBACK: //case AP_BT_LOOPBACK: //case AP_BT_LOOPBACK_NO_CODEC: { AudioALSALoopbackController::getInstance()->open(output_device, input_device); break; } case MD_MAIN_MIC_ACOUSTIC_LOOPBACK: case MD_HEADSET_MIC_ACOUSTIC_LOOPBACK: case MD_DUAL_MIC_ACOUSTIC_LOOPBACK_WITHOUT_DMNR: case MD_DUAL_MIC_ACOUSTIC_LOOPBACK_WITH_DMNR: case MD_REF_MIC_ACOUSTIC_LOOPBACK: case MD_3RD_MIC_ACOUSTIC_LOOPBACK: //case MD_BT_LOOPBACK: //case MD_BT_LOOPBACK_NO_CODEC: { #if defined(MTK_AUDIO_GAIN_TABLE)&&defined(MTK_AUDIO_SPH_LPBK_PARAM) AudioALSAStreamManager::getInstance()->UpdateSpeechLpbkParams(); #endif AudioALSASpeechLoopbackController::getInstance()->open(output_device, input_device); break; } default: { ALOGW("%s(): Loopback type %d not implemented!!", __FUNCTION__, loopback_type); ASSERT(0); } } } /* // only use L ch data, so mute R ch. (Disconnect ADC_I2S_IN_R -> MODEM_PCM_TX_R) if (loopback_type == MD_MAIN_MIC_ACOUSTIC_LOOPBACK || loopback_type == MD_REF_MIC_ACOUSTIC_LOOPBACK) { AudioDigitalControlFactory::CreateAudioDigitalControl()->SetinputConnection( AudioDigitalType::DisConnect, AudioDigitalType::I04, (mWorkingModemIndex == MODEM_1) ? AudioDigitalType::O18 : AudioDigitalType::O08); } */ // save opened loobpack type mLoopbackType = loopback_type; // acquire wake lock int ret = acquire_wake_lock(PARTIAL_WAKE_LOCK, LOOPBACK_WAKELOCK_NAME); ALOGD("%s(), acquire_wake_lock:%s, return %d.", __FUNCTION__, LOOPBACK_WAKELOCK_NAME, ret); // Volume if ((loopback_type != AP_BT_LOOPBACK) && (loopback_type != AP_BT_LOOPBACK_NO_CODEC) && (loopback_type != MD_BT_LOOPBACK) && (loopback_type != MD_BT_LOOPBACK_NO_CODEC)) { if (CheckIsModemLoopback(loopback_type) == true) { mVoiceVolumeCopy = mAudioALSAVolumeController->getVoiceVolume(); mAudioALSAVolumeController->setVoiceVolume(kVoiceVolumeForLoopback, AUDIO_MODE_IN_CALL, output_device); } else { mMasterVolumeCopy = mAudioALSAVolumeController->getMasterVolume(); mAudioALSAVolumeController->setMasterVolume(kMasterVolumeForLoopback, AUDIO_MODE_NORMAL, output_device); } } ALOGD("-%s(), loopback_type = %d, loopback_output_device = %d", __FUNCTION__, loopback_type, loopback_output_device); return NO_ERROR; }