1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* Acoustic Echo Cancellation implementation */ 18#include "sles_allinclusive.h" 19 20#include <media/EffectsFactoryApi.h> 21 22#include <audio_effects/effect_aec.h> 23 24/** 25 * returns true if this interface is not associated with an initialized AEC effect 26 */ 27static inline bool NO_ECHOCANCEL(IAndroidAcousticEchoCancellation* v) { 28 return (v->mAECEffect == 0); 29} 30 31static SLresult IAndroidAcousticEchoCancellation_SetEnabled( 32 SLAndroidAcousticEchoCancellationItf self, 33 SLboolean enabled) 34{ 35 SL_ENTER_INTERFACE 36 37 IAndroidAcousticEchoCancellation *thiz = (IAndroidAcousticEchoCancellation *) self; 38 interface_lock_exclusive(thiz); 39 thiz->mEnabled = (SLboolean) enabled; 40 if (NO_ECHOCANCEL(thiz)) { 41 result = SL_RESULT_CONTROL_LOST; 42 } else { 43 android::status_t status = thiz->mAECEffect->setEnabled((bool) thiz->mEnabled); 44 result = android_fx_statusToResult(status); 45 } 46 interface_unlock_exclusive(thiz); 47 48 SL_LEAVE_INTERFACE 49} 50 51static SLresult IAndroidAcousticEchoCancellation_IsEnabled( 52 SLAndroidAcousticEchoCancellationItf self, 53 SLboolean *pEnabled) 54{ 55 SL_ENTER_INTERFACE 56 57 if (NULL == pEnabled) { 58 result = SL_RESULT_PARAMETER_INVALID; 59 } else { 60 IAndroidAcousticEchoCancellation *thiz = (IAndroidAcousticEchoCancellation *) self; 61 interface_lock_exclusive(thiz); 62 if (NO_ECHOCANCEL(thiz)) { 63 result = SL_RESULT_CONTROL_LOST; 64 } else { 65 *pEnabled = (SLboolean) thiz->mAECEffect->getEnabled(); 66 result = SL_RESULT_SUCCESS; 67 } 68 interface_unlock_exclusive(thiz); 69 } 70 71 SL_LEAVE_INTERFACE 72} 73 74SLresult IAndroidAcousticEchoCancellation_IsAvailable(SLAndroidAcousticEchoCancellationItf self, 75 SLboolean *pEnabled) 76{ 77 SL_ENTER_INTERFACE 78 79 *pEnabled = false; 80 81 uint32_t numEffects = 0; 82 int ret = EffectQueryNumberEffects(&numEffects); 83 if (ret != 0) { 84 ALOGE("IAndroidAcousticEchoCancellation_IsAvailable() error %d querying number of effects", 85 ret); 86 result = SL_RESULT_FEATURE_UNSUPPORTED; 87 } else { 88 ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects); 89 90 effect_descriptor_t fxDesc; 91 for (uint32_t i = 0 ; i < numEffects ; i++) { 92 if (EffectQueryEffect(i, &fxDesc) == 0) { 93 ALOGV("effect %d is called %s", i, fxDesc.name); 94 if (memcmp(&fxDesc.type, SL_IID_ANDROIDACOUSTICECHOCANCELLATION, 95 sizeof(effect_uuid_t)) == 0) { 96 ALOGI("found effect \"%s\" from %s", fxDesc.name, fxDesc.implementor); 97 *pEnabled = true; 98 break; 99 } 100 } 101 } 102 result = SL_RESULT_SUCCESS; 103 } 104 SL_LEAVE_INTERFACE 105} 106 107static const struct SLAndroidAcousticEchoCancellationItf_ IAndroidAcousticEchoCancellation_Itf = { 108 IAndroidAcousticEchoCancellation_SetEnabled, 109 IAndroidAcousticEchoCancellation_IsEnabled, 110 IAndroidAcousticEchoCancellation_IsAvailable 111}; 112 113void IAndroidAcousticEchoCancellation_init(void *self) 114{ 115 IAndroidAcousticEchoCancellation *thiz = (IAndroidAcousticEchoCancellation *) self; 116 thiz->mItf = &IAndroidAcousticEchoCancellation_Itf; 117 thiz->mEnabled = SL_BOOLEAN_FALSE; 118 memset(&thiz->mAECDescriptor, 0, sizeof(effect_descriptor_t)); 119 // placement new (explicit constructor) 120 (void) new (&thiz->mAECEffect) android::sp<android::AudioEffect>(); 121} 122 123void IAndroidAcousticEchoCancellation_deinit(void *self) 124{ 125 IAndroidAcousticEchoCancellation *thiz = (IAndroidAcousticEchoCancellation *) self; 126 // explicit destructor 127 thiz->mAECEffect.~sp(); 128} 129 130bool IAndroidAcousticEchoCancellation_Expose(void *self) 131{ 132 IAndroidAcousticEchoCancellation *thiz = (IAndroidAcousticEchoCancellation *) self; 133 if (!android_fx_initEffectDescriptor(SL_IID_ANDROIDACOUSTICECHOCANCELLATION, 134 &thiz->mAECDescriptor)) { 135 SL_LOGE("Acoustic Echo Cancellation initialization failed."); 136 return false; 137 } 138 return true; 139} 140