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     mClientPid = IPCThreadState::self()->getCallingPid();
132 
133     iEffect = audioFlinger->createEffect((effect_descriptor_t *)&mDescriptor,
134             mIEffectClient, priority, io, mSessionId, mOpPackageName, mClientPid,
135             &mStatus, &mId, &enabled);
136 
137     if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
138         ALOGE("set(): AudioFlinger could not create effect, status: %d", mStatus);
139         if (iEffect == 0) {
140             mStatus = NO_INIT;
141         }
142         return mStatus;
143     }
144 
145     mEnabled = (volatile int32_t)enabled;
146 
147     cblk = iEffect->getCblk();
148     if (cblk == 0) {
149         mStatus = NO_INIT;
150         ALOGE("Could not get control block");
151         return mStatus;
152     }
153 
154     mIEffect = iEffect;
155     mCblkMemory = cblk;
156     mCblk = static_cast<effect_param_cblk_t*>(cblk->pointer());
157     int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
158     mCblk->buffer = (uint8_t *)mCblk + bufOffset;
159 
160     IInterface::asBinder(iEffect)->linkToDeath(mIEffectClient);
161     ALOGV("set() %p OK effect: %s id: %d status %d enabled %d pid %d", this, mDescriptor.name, mId,
162             mStatus, mEnabled, mClientPid);
163 
164     if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
165         AudioSystem::acquireAudioSessionId(mSessionId, mClientPid);
166     }
167 
168     return mStatus;
169 }
170 
171 
~AudioEffect()172 AudioEffect::~AudioEffect()
173 {
174     ALOGV("Destructor %p", this);
175 
176     if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
177         if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
178             AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
179         }
180         if (mIEffect != NULL) {
181             mIEffect->disconnect();
182             IInterface::asBinder(mIEffect)->unlinkToDeath(mIEffectClient);
183         }
184         mIEffect.clear();
185         mCblkMemory.clear();
186         mIEffectClient.clear();
187         IPCThreadState::self()->flushCommands();
188     }
189 }
190 
191 
initCheck() const192 status_t AudioEffect::initCheck() const
193 {
194     return mStatus;
195 }
196 
197 // -------------------------------------------------------------------------
198 
descriptor() const199 effect_descriptor_t AudioEffect::descriptor() const
200 {
201     return mDescriptor;
202 }
203 
getEnabled() const204 bool AudioEffect::getEnabled() const
205 {
206     return (mEnabled != 0);
207 }
208 
setEnabled(bool enabled)209 status_t AudioEffect::setEnabled(bool enabled)
210 {
211     if (mStatus != NO_ERROR) {
212         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
213     }
214 
215     status_t status = NO_ERROR;
216 
217     AutoMutex lock(mLock);
218     if (enabled != mEnabled) {
219         if (enabled) {
220             ALOGV("enable %p", this);
221             status = mIEffect->enable();
222         } else {
223             ALOGV("disable %p", this);
224             status = mIEffect->disable();
225         }
226         if (status == NO_ERROR) {
227             mEnabled = enabled;
228         }
229     }
230     return status;
231 }
232 
command(uint32_t cmdCode,uint32_t cmdSize,void * cmdData,uint32_t * replySize,void * replyData)233 status_t AudioEffect::command(uint32_t cmdCode,
234                               uint32_t cmdSize,
235                               void *cmdData,
236                               uint32_t *replySize,
237                               void *replyData)
238 {
239     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
240         ALOGV("command() bad status %d", mStatus);
241         return mStatus;
242     }
243 
244     if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
245         if (mEnabled == (cmdCode == EFFECT_CMD_ENABLE)) {
246             return NO_ERROR;
247         }
248         if (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL) {
249             return BAD_VALUE;
250         }
251         mLock.lock();
252     }
253 
254     status_t status = mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData);
255 
256     if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
257         if (status == NO_ERROR) {
258             status = *(status_t *)replyData;
259         }
260         if (status == NO_ERROR) {
261             mEnabled = (cmdCode == EFFECT_CMD_ENABLE);
262         }
263         mLock.unlock();
264     }
265 
266     return status;
267 }
268 
269 
setParameter(effect_param_t * param)270 status_t AudioEffect::setParameter(effect_param_t *param)
271 {
272     if (mStatus != NO_ERROR) {
273         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
274     }
275 
276     if (param == NULL || param->psize == 0 || param->vsize == 0) {
277         return BAD_VALUE;
278     }
279 
280     uint32_t size = sizeof(int);
281     uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
282 
283     ALOGV("setParameter: param: %d, param2: %d", *(int *)param->data,
284             (param->psize == 8) ? *((int *)param->data + 1): -1);
285 
286     return mIEffect->command(EFFECT_CMD_SET_PARAM, sizeof (effect_param_t) + psize, param, &size,
287             &param->status);
288 }
289 
setParameterDeferred(effect_param_t * param)290 status_t AudioEffect::setParameterDeferred(effect_param_t *param)
291 {
292     if (mStatus != NO_ERROR) {
293         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
294     }
295 
296     if (param == NULL || param->psize == 0 || param->vsize == 0) {
297         return BAD_VALUE;
298     }
299 
300     Mutex::Autolock _l(mCblk->lock);
301 
302     int psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
303     int size = ((sizeof(effect_param_t) + psize - 1) / sizeof(int) + 1) * sizeof(int);
304 
305     if (mCblk->clientIndex + size > EFFECT_PARAM_BUFFER_SIZE) {
306         return NO_MEMORY;
307     }
308     int *p = (int *)(mCblk->buffer + mCblk->clientIndex);
309     *p++ = size;
310     memcpy(p, param, sizeof(effect_param_t) + psize);
311     mCblk->clientIndex += size;
312 
313     return NO_ERROR;
314 }
315 
setParameterCommit()316 status_t AudioEffect::setParameterCommit()
317 {
318     if (mStatus != NO_ERROR) {
319         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
320     }
321 
322     Mutex::Autolock _l(mCblk->lock);
323     if (mCblk->clientIndex == 0) {
324         return INVALID_OPERATION;
325     }
326     uint32_t size = 0;
327     return mIEffect->command(EFFECT_CMD_SET_PARAM_COMMIT, 0, NULL, &size, NULL);
328 }
329 
getParameter(effect_param_t * param)330 status_t AudioEffect::getParameter(effect_param_t *param)
331 {
332     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
333         return mStatus;
334     }
335 
336     if (param == NULL || param->psize == 0 || param->vsize == 0) {
337         return BAD_VALUE;
338     }
339 
340     ALOGV("getParameter: param: %d, param2: %d", *(int *)param->data,
341             (param->psize == 8) ? *((int *)param->data + 1): -1);
342 
343     uint32_t psize = sizeof(effect_param_t) + ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
344             param->vsize;
345 
346     return mIEffect->command(EFFECT_CMD_GET_PARAM, sizeof(effect_param_t) + param->psize, param,
347             &psize, param);
348 }
349 
350 
351 // -------------------------------------------------------------------------
352 
binderDied()353 void AudioEffect::binderDied()
354 {
355     ALOGW("IEffect died");
356     mStatus = DEAD_OBJECT;
357     if (mCbf != NULL) {
358         status_t status = DEAD_OBJECT;
359         mCbf(EVENT_ERROR, mUserData, &status);
360     }
361     mIEffect.clear();
362 }
363 
364 // -------------------------------------------------------------------------
365 
controlStatusChanged(bool controlGranted)366 void AudioEffect::controlStatusChanged(bool controlGranted)
367 {
368     ALOGV("controlStatusChanged %p control %d callback %p mUserData %p", this, controlGranted, mCbf,
369             mUserData);
370     if (controlGranted) {
371         if (mStatus == ALREADY_EXISTS) {
372             mStatus = NO_ERROR;
373         }
374     } else {
375         if (mStatus == NO_ERROR) {
376             mStatus = ALREADY_EXISTS;
377         }
378     }
379     if (mCbf != NULL) {
380         mCbf(EVENT_CONTROL_STATUS_CHANGED, mUserData, &controlGranted);
381     }
382 }
383 
enableStatusChanged(bool enabled)384 void AudioEffect::enableStatusChanged(bool enabled)
385 {
386     ALOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf);
387     if (mStatus == ALREADY_EXISTS) {
388         mEnabled = enabled;
389         if (mCbf != NULL) {
390             mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
391         }
392     }
393 }
394 
commandExecuted(uint32_t cmdCode,uint32_t cmdSize __unused,void * cmdData,uint32_t replySize __unused,void * replyData)395 void AudioEffect::commandExecuted(uint32_t cmdCode,
396                                   uint32_t cmdSize __unused,
397                                   void *cmdData,
398                                   uint32_t replySize __unused,
399                                   void *replyData)
400 {
401     if (cmdData == NULL || replyData == NULL) {
402         return;
403     }
404 
405     if (mCbf != NULL && cmdCode == EFFECT_CMD_SET_PARAM) {
406         effect_param_t *cmd = (effect_param_t *)cmdData;
407         cmd->status = *(int32_t *)replyData;
408         mCbf(EVENT_PARAMETER_CHANGED, mUserData, cmd);
409     }
410 }
411 
412 // -------------------------------------------------------------------------
413 
queryNumberEffects(uint32_t * numEffects)414 status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
415 {
416     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
417     if (af == 0) return PERMISSION_DENIED;
418     return af->queryNumberEffects(numEffects);
419 }
420 
queryEffect(uint32_t index,effect_descriptor_t * descriptor)421 status_t AudioEffect::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
422 {
423     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
424     if (af == 0) return PERMISSION_DENIED;
425     return af->queryEffect(index, descriptor);
426 }
427 
getEffectDescriptor(const effect_uuid_t * uuid,effect_descriptor_t * descriptor)428 status_t AudioEffect::getEffectDescriptor(const effect_uuid_t *uuid,
429         effect_descriptor_t *descriptor) /*const*/
430 {
431     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
432     if (af == 0) return PERMISSION_DENIED;
433     return af->getEffectDescriptor(uuid, descriptor);
434 }
435 
436 
queryDefaultPreProcessing(audio_session_t audioSession,effect_descriptor_t * descriptors,uint32_t * count)437 status_t AudioEffect::queryDefaultPreProcessing(audio_session_t audioSession,
438                                           effect_descriptor_t *descriptors,
439                                           uint32_t *count)
440 {
441     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
442     if (aps == 0) return PERMISSION_DENIED;
443     return aps->queryDefaultPreProcessing(audioSession, descriptors, count);
444 }
445 // -------------------------------------------------------------------------
446 
stringToGuid(const char * str,effect_uuid_t * guid)447 status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
448 {
449     if (str == NULL || guid == NULL) {
450         return BAD_VALUE;
451     }
452 
453     int tmp[10];
454 
455     if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
456             tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
457         return BAD_VALUE;
458     }
459     guid->timeLow = (uint32_t)tmp[0];
460     guid->timeMid = (uint16_t)tmp[1];
461     guid->timeHiAndVersion = (uint16_t)tmp[2];
462     guid->clockSeq = (uint16_t)tmp[3];
463     guid->node[0] = (uint8_t)tmp[4];
464     guid->node[1] = (uint8_t)tmp[5];
465     guid->node[2] = (uint8_t)tmp[6];
466     guid->node[3] = (uint8_t)tmp[7];
467     guid->node[4] = (uint8_t)tmp[8];
468     guid->node[5] = (uint8_t)tmp[9];
469 
470     return NO_ERROR;
471 }
472 
guidToString(const effect_uuid_t * guid,char * str,size_t maxLen)473 status_t AudioEffect::guidToString(const effect_uuid_t *guid, char *str, size_t maxLen)
474 {
475     if (guid == NULL || str == NULL) {
476         return BAD_VALUE;
477     }
478 
479     snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
480             guid->timeLow,
481             guid->timeMid,
482             guid->timeHiAndVersion,
483             guid->clockSeq,
484             guid->node[0],
485             guid->node[1],
486             guid->node[2],
487             guid->node[3],
488             guid->node[4],
489             guid->node[5]);
490 
491     return NO_ERROR;
492 }
493 
494 
495 } // namespace android
496