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 /* Automatic Gain Control implementation */
18 #include "sles_allinclusive.h"
19 
20 #include <media/EffectsFactoryApi.h>
21 
22 #include <audio_effects/effect_agc.h>
23 
24 /**
25  * returns true if this interface is not associated with an initialized AGC effect
26  */
NO_AUTOGAIN(IAndroidAutomaticGainControl * v)27 static inline bool NO_AUTOGAIN(IAndroidAutomaticGainControl* v) {
28     return (v->mAGCEffect == 0);
29 }
30 
IAndroidAutomaticGainControl_SetEnabled(SLAndroidAutomaticGainControlItf self,SLboolean enabled)31 SLresult IAndroidAutomaticGainControl_SetEnabled(SLAndroidAutomaticGainControlItf self, SLboolean enabled)
32 {
33     SL_ENTER_INTERFACE
34 
35     IAndroidAutomaticGainControl *thiz = (IAndroidAutomaticGainControl *) self;
36     interface_lock_exclusive(thiz);
37     thiz->mEnabled = (SLboolean) enabled;
38     if (NO_AUTOGAIN(thiz)) {
39         result = SL_RESULT_CONTROL_LOST;
40     } else {
41         android::status_t status = thiz->mAGCEffect->setEnabled((bool) thiz->mEnabled);
42         result = android_fx_statusToResult(status);
43     }
44     interface_unlock_exclusive(thiz);
45 
46     SL_LEAVE_INTERFACE
47 }
48 
IAndroidAutomaticGainControl_IsEnabled(SLAndroidAutomaticGainControlItf self,SLboolean * pEnabled)49 SLresult IAndroidAutomaticGainControl_IsEnabled(SLAndroidAutomaticGainControlItf self, SLboolean *pEnabled)
50 {
51     SL_ENTER_INTERFACE
52 
53     if (NULL == pEnabled) {
54         result = SL_RESULT_PARAMETER_INVALID;
55     } else {
56         IAndroidAutomaticGainControl *thiz = (IAndroidAutomaticGainControl *) self;
57         interface_lock_exclusive(thiz);
58         SLboolean enabled = thiz->mEnabled;
59         if (NO_AUTOGAIN(thiz)) {
60             result = SL_RESULT_CONTROL_LOST;
61         } else {
62             *pEnabled = (SLboolean) thiz->mAGCEffect->getEnabled();
63             result = SL_RESULT_SUCCESS;
64         }
65         interface_unlock_exclusive(thiz);
66     }
67     SL_LEAVE_INTERFACE
68 }
69 
IAndroidAutomaticGainControl_IsAvailable(SLAndroidAutomaticGainControlItf self,SLboolean * pEnabled)70 SLresult IAndroidAutomaticGainControl_IsAvailable(SLAndroidAutomaticGainControlItf self,
71                                                   SLboolean *pEnabled)
72 {
73     SL_ENTER_INTERFACE
74 
75    *pEnabled = false;
76 
77     uint32_t numEffects = 0;
78     int ret = EffectQueryNumberEffects(&numEffects);
79     if (ret != 0) {
80         ALOGE("IAndroidAutomaticGainControl_IsAvailable() error %d querying number of effects",
81               ret);
82         result = SL_RESULT_FEATURE_UNSUPPORTED;
83    } else {
84         ALOGV("EffectQueryNumberEffects() numEffects=%d", numEffects);
85 
86         effect_descriptor_t fxDesc;
87         for (uint32_t i = 0 ; i < numEffects ; i++) {
88             if (EffectQueryEffect(i, &fxDesc) == 0) {
89                 ALOGV("effect %d is called %s", i, fxDesc.name);
90                 if (memcmp(&fxDesc.type, SL_IID_ANDROIDAUTOMATICGAINCONTROL,
91                            sizeof(effect_uuid_t)) == 0) {
92                     ALOGI("found effect \"%s\" from %s", fxDesc.name, fxDesc.implementor);
93                     *pEnabled = true;
94                     break;
95                 }
96             }
97         }
98         result = SL_RESULT_SUCCESS;
99     }
100     SL_LEAVE_INTERFACE
101 }
102 
103 static const struct SLAndroidAutomaticGainControlItf_ IAndroidAutomaticGainControl_Itf = {
104     IAndroidAutomaticGainControl_SetEnabled,
105     IAndroidAutomaticGainControl_IsEnabled,
106     IAndroidAutomaticGainControl_IsAvailable
107 };
108 
IAndroidAutomaticGainControl_init(void * self)109 void IAndroidAutomaticGainControl_init(void *self)
110 {
111     IAndroidAutomaticGainControl *thiz = (IAndroidAutomaticGainControl *) self;
112     thiz->mItf = &IAndroidAutomaticGainControl_Itf;
113     thiz->mEnabled = SL_BOOLEAN_FALSE;
114     memset(&thiz->mAGCDescriptor, 0, sizeof(effect_descriptor_t));
115     // placement new (explicit constructor)
116     (void) new (&thiz->mAGCEffect) android::sp<android::AudioEffect>();
117 }
118 
IAndroidAutomaticGainControl_deinit(void * self)119 void IAndroidAutomaticGainControl_deinit(void *self)
120 {
121     IAndroidAutomaticGainControl *thiz = (IAndroidAutomaticGainControl *) self;
122     // explicit destructor
123     thiz->mAGCEffect.~sp();
124 }
125 
IAndroidAutomaticGainControl_Expose(void * self)126 bool IAndroidAutomaticGainControl_Expose(void *self)
127 {
128     IAndroidAutomaticGainControl *thiz = (IAndroidAutomaticGainControl *) self;
129     if (!android_fx_initEffectDescriptor(SL_IID_ANDROIDAUTOMATICGAINCONTROL,
130                                          &thiz->mAGCDescriptor)) {
131         SL_LOGE("Automatic Gain Control initialization failed.");
132         return false;
133     }
134     return true;
135 }
136