1 /*
2 **
3 ** Copyright 2010, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17 
18 
19 //#define LOG_NDEBUG 0
20 #define LOG_TAG "AudioEffect"
21 
22 #include <stdint.h>
23 #include <sys/types.h>
24 #include <limits.h>
25 
26 #include <private/media/AudioEffectShared.h>
27 #include <media/AudioEffect.h>
28 
29 #include <utils/Log.h>
30 #include <binder/IPCThreadState.h>
31 
32 
33 
34 namespace android {
35 
36 // ---------------------------------------------------------------------------
37 
AudioEffect(const String16 & opPackageName)38 AudioEffect::AudioEffect(const String16& opPackageName)
39     : mStatus(NO_INIT), mOpPackageName(opPackageName)
40 {
41 }
42 
43 
AudioEffect(const effect_uuid_t * type,const String16 & opPackageName,const effect_uuid_t * uuid,int32_t priority,effect_callback_t cbf,void * user,audio_session_t sessionId,audio_io_handle_t io)44 AudioEffect::AudioEffect(const effect_uuid_t *type,
45                 const String16& opPackageName,
46                 const effect_uuid_t *uuid,
47                 int32_t priority,
48                 effect_callback_t cbf,
49                 void* user,
50                 audio_session_t sessionId,
51                 audio_io_handle_t io
52                 )
53     : mStatus(NO_INIT), mOpPackageName(opPackageName)
54 {
55     mStatus = set(type, uuid, priority, cbf, user, sessionId, io);
56 }
57 
AudioEffect(const char * typeStr,const String16 & opPackageName,const char * uuidStr,int32_t priority,effect_callback_t cbf,void * user,audio_session_t sessionId,audio_io_handle_t io)58 AudioEffect::AudioEffect(const char *typeStr,
59                 const String16& opPackageName,
60                 const char *uuidStr,
61                 int32_t priority,
62                 effect_callback_t cbf,
63                 void* user,
64                 audio_session_t sessionId,
65                 audio_io_handle_t io
66                 )
67     : mStatus(NO_INIT), mOpPackageName(opPackageName)
68 {
69     effect_uuid_t type;
70     effect_uuid_t *pType = NULL;
71     effect_uuid_t uuid;
72     effect_uuid_t *pUuid = NULL;
73 
74     ALOGV("Constructor string\n - type: %s\n - uuid: %s", typeStr, uuidStr);
75 
76     if (typeStr != NULL) {
77         if (stringToGuid(typeStr, &type) == NO_ERROR) {
78             pType = &type;
79         }
80     }
81 
82     if (uuidStr != NULL) {
83         if (stringToGuid(uuidStr, &uuid) == NO_ERROR) {
84             pUuid = &uuid;
85         }
86     }
87 
88     mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io);
89 }
90 
set(const effect_uuid_t * type,const effect_uuid_t * uuid,int32_t priority,effect_callback_t cbf,void * user,audio_session_t sessionId,audio_io_handle_t io)91 status_t AudioEffect::set(const effect_uuid_t *type,
92                 const effect_uuid_t *uuid,
93                 int32_t priority,
94                 effect_callback_t cbf,
95                 void* user,
96                 audio_session_t sessionId,
97                 audio_io_handle_t io)
98 {
99     sp<IEffect> iEffect;
100     sp<IMemory> cblk;
101     int enabled;
102 
103     ALOGV("set %p mUserData: %p uuid: %p timeLow %08x", this, user, type, type ? type->timeLow : 0);
104 
105     if (mIEffect != 0) {
106         ALOGW("Effect already in use");
107         return INVALID_OPERATION;
108     }
109 
110     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
111     if (audioFlinger == 0) {
112         ALOGE("set(): Could not get audioflinger");
113         return NO_INIT;
114     }
115 
116     if (type == NULL && uuid == NULL) {
117         ALOGW("Must specify at least type or uuid");
118         return BAD_VALUE;
119     }
120 
121     mPriority = priority;
122     mCbf = cbf;
123     mUserData = user;
124     mSessionId = sessionId;
125 
126     memset(&mDescriptor, 0, sizeof(effect_descriptor_t));
127     mDescriptor.type = *(type != NULL ? type : EFFECT_UUID_NULL);
128     mDescriptor.uuid = *(uuid != NULL ? uuid : EFFECT_UUID_NULL);
129 
130     mIEffectClient = new EffectClient(this);
131 
132     iEffect = audioFlinger->createEffect((effect_descriptor_t *)&mDescriptor,
133             mIEffectClient, priority, io, mSessionId, mOpPackageName, &mStatus, &mId, &enabled);
134 
135     if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
136         ALOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);
137         if (iEffect == 0) {
138             mStatus = NO_INIT;
139         }
140         return mStatus;
141     }
142 
143     mEnabled = (volatile int32_t)enabled;
144 
145     cblk = iEffect->getCblk();
146     if (cblk == 0) {
147         mStatus = NO_INIT;
148         ALOGE("Could not get control block");
149         return mStatus;
150     }
151 
152     mIEffect = iEffect;
153     mCblkMemory = cblk;
154     mCblk = static_cast<effect_param_cblk_t*>(cblk->pointer());
155     int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
156     mCblk->buffer = (uint8_t *)mCblk + bufOffset;
157 
158     IInterface::asBinder(iEffect)->linkToDeath(mIEffectClient);
159     mClientPid = IPCThreadState::self()->getCallingPid();
160     ALOGV("set() %p OK effect: %s id: %d status %d enabled %d pid %d", this, mDescriptor.name, mId,
161             mStatus, mEnabled, mClientPid);
162 
163     if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
164         AudioSystem::acquireAudioSessionId(mSessionId, mClientPid);
165     }
166 
167     return mStatus;
168 }
169 
170 
~AudioEffect()171 AudioEffect::~AudioEffect()
172 {
173     ALOGV("Destructor %p", this);
174 
175     if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
176         if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
177             AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
178         }
179         if (mIEffect != NULL) {
180             mIEffect->disconnect();
181             IInterface::asBinder(mIEffect)->unlinkToDeath(mIEffectClient);
182         }
183         mIEffect.clear();
184         mCblkMemory.clear();
185         mIEffectClient.clear();
186         IPCThreadState::self()->flushCommands();
187     }
188 }
189 
190 
initCheck() const191 status_t AudioEffect::initCheck() const
192 {
193     return mStatus;
194 }
195 
196 // -------------------------------------------------------------------------
197 
descriptor() const198 effect_descriptor_t AudioEffect::descriptor() const
199 {
200     return mDescriptor;
201 }
202 
getEnabled() const203 bool AudioEffect::getEnabled() const
204 {
205     return (mEnabled != 0);
206 }
207 
setEnabled(bool enabled)208 status_t AudioEffect::setEnabled(bool enabled)
209 {
210     if (mStatus != NO_ERROR) {
211         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
212     }
213 
214     status_t status = NO_ERROR;
215 
216     AutoMutex lock(mLock);
217     if (enabled != mEnabled) {
218         if (enabled) {
219             ALOGV("enable %p", this);
220             status = mIEffect->enable();
221         } else {
222             ALOGV("disable %p", this);
223             status = mIEffect->disable();
224         }
225         if (status == NO_ERROR) {
226             mEnabled = enabled;
227         }
228     }
229     return status;
230 }
231 
command(uint32_t cmdCode,uint32_t cmdSize,void * cmdData,uint32_t * replySize,void * replyData)232 status_t AudioEffect::command(uint32_t cmdCode,
233                               uint32_t cmdSize,
234                               void *cmdData,
235                               uint32_t *replySize,
236                               void *replyData)
237 {
238     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
239         ALOGV("command() bad status %d", mStatus);
240         return mStatus;
241     }
242 
243     if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
244         if (mEnabled == (cmdCode == EFFECT_CMD_ENABLE)) {
245             return NO_ERROR;
246         }
247         if (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL) {
248             return BAD_VALUE;
249         }
250         mLock.lock();
251     }
252 
253     status_t status = mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData);
254 
255     if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
256         if (status == NO_ERROR) {
257             status = *(status_t *)replyData;
258         }
259         if (status == NO_ERROR) {
260             mEnabled = (cmdCode == EFFECT_CMD_ENABLE);
261         }
262         mLock.unlock();
263     }
264 
265     return status;
266 }
267 
268 
setParameter(effect_param_t * param)269 status_t AudioEffect::setParameter(effect_param_t *param)
270 {
271     if (mStatus != NO_ERROR) {
272         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
273     }
274 
275     if (param == NULL || param->psize == 0 || param->vsize == 0) {
276         return BAD_VALUE;
277     }
278 
279     uint32_t size = sizeof(int);
280     uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
281 
282     ALOGV("setParameter: param: %d, param2: %d", *(int *)param->data,
283             (param->psize == 8) ? *((int *)param->data + 1): -1);
284 
285     return mIEffect->command(EFFECT_CMD_SET_PARAM, sizeof (effect_param_t) + psize, param, &size,
286             &param->status);
287 }
288 
setParameterDeferred(effect_param_t * param)289 status_t AudioEffect::setParameterDeferred(effect_param_t *param)
290 {
291     if (mStatus != NO_ERROR) {
292         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
293     }
294 
295     if (param == NULL || param->psize == 0 || param->vsize == 0) {
296         return BAD_VALUE;
297     }
298 
299     Mutex::Autolock _l(mCblk->lock);
300 
301     int psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
302     int size = ((sizeof(effect_param_t) + psize - 1) / sizeof(int) + 1) * sizeof(int);
303 
304     if (mCblk->clientIndex + size > EFFECT_PARAM_BUFFER_SIZE) {
305         return NO_MEMORY;
306     }
307     int *p = (int *)(mCblk->buffer + mCblk->clientIndex);
308     *p++ = size;
309     memcpy(p, param, sizeof(effect_param_t) + psize);
310     mCblk->clientIndex += size;
311 
312     return NO_ERROR;
313 }
314 
setParameterCommit()315 status_t AudioEffect::setParameterCommit()
316 {
317     if (mStatus != NO_ERROR) {
318         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
319     }
320 
321     Mutex::Autolock _l(mCblk->lock);
322     if (mCblk->clientIndex == 0) {
323         return INVALID_OPERATION;
324     }
325     uint32_t size = 0;
326     return mIEffect->command(EFFECT_CMD_SET_PARAM_COMMIT, 0, NULL, &size, NULL);
327 }
328 
getParameter(effect_param_t * param)329 status_t AudioEffect::getParameter(effect_param_t *param)
330 {
331     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
332         return mStatus;
333     }
334 
335     if (param == NULL || param->psize == 0 || param->vsize == 0) {
336         return BAD_VALUE;
337     }
338 
339     ALOGV("getParameter: param: %d, param2: %d", *(int *)param->data,
340             (param->psize == 8) ? *((int *)param->data + 1): -1);
341 
342     uint32_t psize = sizeof(effect_param_t) + ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
343             param->vsize;
344 
345     return mIEffect->command(EFFECT_CMD_GET_PARAM, sizeof(effect_param_t) + param->psize, param,
346             &psize, param);
347 }
348 
349 
350 // -------------------------------------------------------------------------
351 
binderDied()352 void AudioEffect::binderDied()
353 {
354     ALOGW("IEffect died");
355     mStatus = DEAD_OBJECT;
356     if (mCbf != NULL) {
357         status_t status = DEAD_OBJECT;
358         mCbf(EVENT_ERROR, mUserData, &status);
359     }
360     mIEffect.clear();
361 }
362 
363 // -------------------------------------------------------------------------
364 
controlStatusChanged(bool controlGranted)365 void AudioEffect::controlStatusChanged(bool controlGranted)
366 {
367     ALOGV("controlStatusChanged %p control %d callback %p mUserData %p", this, controlGranted, mCbf,
368             mUserData);
369     if (controlGranted) {
370         if (mStatus == ALREADY_EXISTS) {
371             mStatus = NO_ERROR;
372         }
373     } else {
374         if (mStatus == NO_ERROR) {
375             mStatus = ALREADY_EXISTS;
376         }
377     }
378     if (mCbf != NULL) {
379         mCbf(EVENT_CONTROL_STATUS_CHANGED, mUserData, &controlGranted);
380     }
381 }
382 
enableStatusChanged(bool enabled)383 void AudioEffect::enableStatusChanged(bool enabled)
384 {
385     ALOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf);
386     if (mStatus == ALREADY_EXISTS) {
387         mEnabled = enabled;
388         if (mCbf != NULL) {
389             mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
390         }
391     }
392 }
393 
commandExecuted(uint32_t cmdCode,uint32_t cmdSize __unused,void * cmdData,uint32_t replySize __unused,void * replyData)394 void AudioEffect::commandExecuted(uint32_t cmdCode,
395                                   uint32_t cmdSize __unused,
396                                   void *cmdData,
397                                   uint32_t replySize __unused,
398                                   void *replyData)
399 {
400     if (cmdData == NULL || replyData == NULL) {
401         return;
402     }
403 
404     if (mCbf != NULL && cmdCode == EFFECT_CMD_SET_PARAM) {
405         effect_param_t *cmd = (effect_param_t *)cmdData;
406         cmd->status = *(int32_t *)replyData;
407         mCbf(EVENT_PARAMETER_CHANGED, mUserData, cmd);
408     }
409 }
410 
411 // -------------------------------------------------------------------------
412 
queryNumberEffects(uint32_t * numEffects)413 status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
414 {
415     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
416     if (af == 0) return PERMISSION_DENIED;
417     return af->queryNumberEffects(numEffects);
418 }
419 
queryEffect(uint32_t index,effect_descriptor_t * descriptor)420 status_t AudioEffect::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
421 {
422     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
423     if (af == 0) return PERMISSION_DENIED;
424     return af->queryEffect(index, descriptor);
425 }
426 
getEffectDescriptor(const effect_uuid_t * uuid,effect_descriptor_t * descriptor)427 status_t AudioEffect::getEffectDescriptor(const effect_uuid_t *uuid,
428         effect_descriptor_t *descriptor) /*const*/
429 {
430     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
431     if (af == 0) return PERMISSION_DENIED;
432     return af->getEffectDescriptor(uuid, descriptor);
433 }
434 
435 
queryDefaultPreProcessing(audio_session_t audioSession,effect_descriptor_t * descriptors,uint32_t * count)436 status_t AudioEffect::queryDefaultPreProcessing(audio_session_t audioSession,
437                                           effect_descriptor_t *descriptors,
438                                           uint32_t *count)
439 {
440     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
441     if (aps == 0) return PERMISSION_DENIED;
442     return aps->queryDefaultPreProcessing(audioSession, descriptors, count);
443 }
444 // -------------------------------------------------------------------------
445 
stringToGuid(const char * str,effect_uuid_t * guid)446 status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
447 {
448     if (str == NULL || guid == NULL) {
449         return BAD_VALUE;
450     }
451 
452     int tmp[10];
453 
454     if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
455             tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
456         return BAD_VALUE;
457     }
458     guid->timeLow = (uint32_t)tmp[0];
459     guid->timeMid = (uint16_t)tmp[1];
460     guid->timeHiAndVersion = (uint16_t)tmp[2];
461     guid->clockSeq = (uint16_t)tmp[3];
462     guid->node[0] = (uint8_t)tmp[4];
463     guid->node[1] = (uint8_t)tmp[5];
464     guid->node[2] = (uint8_t)tmp[6];
465     guid->node[3] = (uint8_t)tmp[7];
466     guid->node[4] = (uint8_t)tmp[8];
467     guid->node[5] = (uint8_t)tmp[9];
468 
469     return NO_ERROR;
470 }
471 
guidToString(const effect_uuid_t * guid,char * str,size_t maxLen)472 status_t AudioEffect::guidToString(const effect_uuid_t *guid, char *str, size_t maxLen)
473 {
474     if (guid == NULL || str == NULL) {
475         return BAD_VALUE;
476     }
477 
478     snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
479             guid->timeLow,
480             guid->timeMid,
481             guid->timeHiAndVersion,
482             guid->clockSeq,
483             guid->node[0],
484             guid->node[1],
485             guid->node[2],
486             guid->node[3],
487             guid->node[4],
488             guid->node[5]);
489 
490     return NO_ERROR;
491 }
492 
493 
494 } // namespace android
495