1 /*
2  * Copyright (C) 2018 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 #define LOG_TAG "EffectFactoryHAL"
18 #include "EffectsFactory.h"
19 #include "AcousticEchoCancelerEffect.h"
20 #include "AutomaticGainControlEffect.h"
21 #include "BassBoostEffect.h"
22 #include "DownmixEffect.h"
23 #include "Effect.h"
24 #include "EnvironmentalReverbEffect.h"
25 #include "EqualizerEffect.h"
26 #include "LoudnessEnhancerEffect.h"
27 #include "NoiseSuppressionEffect.h"
28 #include "PresetReverbEffect.h"
29 #include "VirtualizerEffect.h"
30 #include "VisualizerEffect.h"
31 #include "common/all-versions/default/EffectMap.h"
32 
33 #include <UuidUtils.h>
34 #include <android/log.h>
35 #include <media/EffectsFactoryApi.h>
36 #include <system/audio_effects/effect_aec.h>
37 #include <system/audio_effects/effect_agc.h>
38 #include <system/audio_effects/effect_bassboost.h>
39 #include <system/audio_effects/effect_downmix.h>
40 #include <system/audio_effects/effect_environmentalreverb.h>
41 #include <system/audio_effects/effect_equalizer.h>
42 #include <system/audio_effects/effect_loudnessenhancer.h>
43 #include <system/audio_effects/effect_ns.h>
44 #include <system/audio_effects/effect_presetreverb.h>
45 #include <system/audio_effects/effect_virtualizer.h>
46 #include <system/audio_effects/effect_visualizer.h>
47 #include <util/EffectUtils.h>
48 
49 namespace android {
50 namespace hardware {
51 namespace audio {
52 namespace effect {
53 namespace CPP_VERSION {
54 namespace implementation {
55 
56 using ::android::hardware::audio::common::CPP_VERSION::implementation::UuidUtils;
57 
58 // static
dispatchEffectInstanceCreation(const effect_descriptor_t & halDescriptor,effect_handle_t handle)59 sp<IEffect> EffectsFactory::dispatchEffectInstanceCreation(const effect_descriptor_t& halDescriptor,
60                                                            effect_handle_t handle) {
61     const effect_uuid_t* halUuid = &halDescriptor.type;
62     if (memcmp(halUuid, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
63         return new AcousticEchoCancelerEffect(handle);
64     } else if (memcmp(halUuid, FX_IID_AGC, sizeof(effect_uuid_t)) == 0) {
65         return new AutomaticGainControlEffect(handle);
66     } else if (memcmp(halUuid, SL_IID_BASSBOOST, sizeof(effect_uuid_t)) == 0) {
67         return new BassBoostEffect(handle);
68     } else if (memcmp(halUuid, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
69         return new DownmixEffect(handle);
70     } else if (memcmp(halUuid, SL_IID_ENVIRONMENTALREVERB, sizeof(effect_uuid_t)) == 0) {
71         return new EnvironmentalReverbEffect(handle);
72     } else if (memcmp(halUuid, SL_IID_EQUALIZER, sizeof(effect_uuid_t)) == 0) {
73         return new EqualizerEffect(handle);
74     } else if (memcmp(halUuid, FX_IID_LOUDNESS_ENHANCER, sizeof(effect_uuid_t)) == 0) {
75         return new LoudnessEnhancerEffect(handle);
76     } else if (memcmp(halUuid, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
77         return new NoiseSuppressionEffect(handle);
78     } else if (memcmp(halUuid, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
79         return new PresetReverbEffect(handle);
80     } else if (memcmp(halUuid, SL_IID_VIRTUALIZER, sizeof(effect_uuid_t)) == 0) {
81         return new VirtualizerEffect(handle);
82     } else if (memcmp(halUuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) {
83         return new VisualizerEffect(handle);
84     }
85     const bool isInput =
86             (halDescriptor.flags & EFFECT_FLAG_TYPE_PRE_PROC) == EFFECT_FLAG_TYPE_PRE_PROC;
87     return new Effect(isInput, handle);
88 }
89 
90 // Methods from ::android::hardware::audio::effect::CPP_VERSION::IEffectsFactory follow.
getAllDescriptors(getAllDescriptors_cb _hidl_cb)91 Return<void> EffectsFactory::getAllDescriptors(getAllDescriptors_cb _hidl_cb) {
92     Result retval(Result::OK);
93     hidl_vec<EffectDescriptor> result;
94     uint32_t numEffects;
95     status_t status;
96 
97 restart:
98     numEffects = 0;
99     status = EffectQueryNumberEffects(&numEffects);
100     if (status != OK) {
101         retval = Result::NOT_INITIALIZED;
102         ALOGE("Error querying number of effects: %s", strerror(-status));
103         goto exit;
104     }
105     result.resize(numEffects);
106     for (uint32_t i = 0; i < numEffects; ++i) {
107         effect_descriptor_t halDescriptor;
108         status = EffectQueryEffect(i, &halDescriptor);
109         if (status == OK) {
110             EffectUtils::effectDescriptorFromHal(halDescriptor, &result[i]);
111         } else {
112             ALOGE("Error querying effect at position %d / %d: %s", i, numEffects,
113                   strerror(-status));
114             switch (status) {
115                 case -ENOSYS: {
116                     // Effect list has changed.
117                     goto restart;
118                 }
119                 case -ENOENT: {
120                     // No more effects available.
121                     result.resize(i);
122                     break;
123                 }
124                 default: {
125                     result.resize(0);
126                     retval = Result::NOT_INITIALIZED;
127                 }
128             }
129             break;
130         }
131     }
132 
133 exit:
134     _hidl_cb(retval, result);
135     return Void();
136 }
137 
getDescriptor(const Uuid & uuid,getDescriptor_cb _hidl_cb)138 Return<void> EffectsFactory::getDescriptor(const Uuid& uuid, getDescriptor_cb _hidl_cb) {
139     effect_uuid_t halUuid;
140     UuidUtils::uuidToHal(uuid, &halUuid);
141     effect_descriptor_t halDescriptor;
142     status_t status = EffectGetDescriptor(&halUuid, &halDescriptor);
143     EffectDescriptor descriptor;
144     EffectUtils::effectDescriptorFromHal(halDescriptor, &descriptor);
145     Result retval(Result::OK);
146     if (status != OK) {
147         ALOGE("Error querying effect descriptor for %s: %s",
148               UuidUtils::uuidToString(halUuid).c_str(), strerror(-status));
149         if (status == -ENOENT) {
150             retval = Result::INVALID_ARGUMENTS;
151         } else {
152             retval = Result::NOT_INITIALIZED;
153         }
154     }
155     _hidl_cb(retval, descriptor);
156     return Void();
157 }
158 
159 #if MAJOR_VERSION <= 5
createEffect(const Uuid & uuid,int32_t session,int32_t ioHandle,EffectsFactory::createEffect_cb _hidl_cb)160 Return<void> EffectsFactory::createEffect(const Uuid& uuid, int32_t session, int32_t ioHandle,
161                                           EffectsFactory::createEffect_cb _hidl_cb) {
162     return createEffectImpl(uuid, session, ioHandle, AUDIO_PORT_HANDLE_NONE, _hidl_cb);
163 }
164 #else
createEffect(const Uuid & uuid,int32_t session,int32_t ioHandle,int32_t device,EffectsFactory::createEffect_cb _hidl_cb)165 Return<void> EffectsFactory::createEffect(const Uuid& uuid, int32_t session, int32_t ioHandle,
166                                           int32_t device,
167                                           EffectsFactory::createEffect_cb _hidl_cb) {
168     return createEffectImpl(uuid, session, ioHandle, device, _hidl_cb);
169 }
170 #endif
171 
createEffectImpl(const Uuid & uuid,int32_t session,int32_t ioHandle,int32_t device,createEffect_cb _hidl_cb)172 Return<void> EffectsFactory::createEffectImpl(const Uuid& uuid, int32_t session, int32_t ioHandle,
173                                               int32_t device, createEffect_cb _hidl_cb) {
174     effect_uuid_t halUuid;
175     UuidUtils::uuidToHal(uuid, &halUuid);
176     effect_handle_t handle;
177     Result retval(Result::OK);
178     status_t status;
179     if (session == AUDIO_SESSION_DEVICE) {
180         status = EffectCreateOnDevice(&halUuid, device, ioHandle, &handle);
181     } else {
182         status = EffectCreate(&halUuid, session, ioHandle, &handle);
183     }
184     sp<IEffect> effect;
185     uint64_t effectId = EffectMap::INVALID_ID;
186     if (status == OK) {
187         effect_descriptor_t halDescriptor;
188         memset(&halDescriptor, 0, sizeof(effect_descriptor_t));
189         status = (*handle)->get_descriptor(handle, &halDescriptor);
190         if (status == OK) {
191             effect = dispatchEffectInstanceCreation(halDescriptor, handle);
192             effectId = EffectMap::getInstance().add(handle);
193         } else {
194             ALOGE("Error querying effect descriptor for %s: %s",
195                   UuidUtils::uuidToString(halUuid).c_str(), strerror(-status));
196             EffectRelease(handle);
197         }
198     }
199     if (status != OK) {
200         ALOGE("Error creating effect %s: %s", UuidUtils::uuidToString(halUuid).c_str(),
201               strerror(-status));
202         if (status == -ENOENT) {
203             retval = Result::INVALID_ARGUMENTS;
204         } else {
205             retval = Result::NOT_INITIALIZED;
206         }
207     }
208     _hidl_cb(retval, effect, effectId);
209     return Void();
210 }
211 
debugDump(const hidl_handle & fd)212 Return<void> EffectsFactory::debugDump(const hidl_handle& fd) {
213     return debug(fd, {} /* options */);
214 }
215 
debug(const hidl_handle & fd,const hidl_vec<hidl_string> &)216 Return<void> EffectsFactory::debug(const hidl_handle& fd,
217                                    const hidl_vec<hidl_string>& /* options */) {
218     if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
219         EffectDumpEffects(fd->data[0]);
220     }
221     return Void();
222 }
223 
HIDL_FETCH_IEffectsFactory(const char * name)224 IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* name) {
225     return strcmp(name, "default") == 0 ? new EffectsFactory() : nullptr;
226 }
227 
228 }  // namespace implementation
229 }  // namespace CPP_VERSION
230 }  // namespace effect
231 }  // namespace audio
232 }  // namespace hardware
233 }  // namespace android
234