• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     AutoMutex lock(mConstructLock);
56     mStatus = set(type, uuid, priority, cbf, user, sessionId, io);
57 }
58 
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)59 AudioEffect::AudioEffect(const char *typeStr,
60                 const String16& opPackageName,
61                 const char *uuidStr,
62                 int32_t priority,
63                 effect_callback_t cbf,
64                 void* user,
65                 audio_session_t sessionId,
66                 audio_io_handle_t io
67                 )
68     : mStatus(NO_INIT), mOpPackageName(opPackageName)
69 {
70     effect_uuid_t type;
71     effect_uuid_t *pType = NULL;
72     effect_uuid_t uuid;
73     effect_uuid_t *pUuid = NULL;
74 
75     ALOGV("Constructor string\n - type: %s\n - uuid: %s", typeStr, uuidStr);
76 
77     if (typeStr != NULL) {
78         if (stringToGuid(typeStr, &type) == NO_ERROR) {
79             pType = &type;
80         }
81     }
82 
83     if (uuidStr != NULL) {
84         if (stringToGuid(uuidStr, &uuid) == NO_ERROR) {
85             pUuid = &uuid;
86         }
87     }
88 
89     AutoMutex lock(mConstructLock);
90     mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io);
91 }
92 
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)93 status_t AudioEffect::set(const effect_uuid_t *type,
94                 const effect_uuid_t *uuid,
95                 int32_t priority,
96                 effect_callback_t cbf,
97                 void* user,
98                 audio_session_t sessionId,
99                 audio_io_handle_t io)
100 {
101     sp<IEffect> iEffect;
102     sp<IMemory> cblk;
103     int enabled;
104 
105     ALOGV("set %p mUserData: %p uuid: %p timeLow %08x", this, user, type, type ? type->timeLow : 0);
106 
107     if (mIEffect != 0) {
108         ALOGW("Effect already in use");
109         return INVALID_OPERATION;
110     }
111 
112     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
113     if (audioFlinger == 0) {
114         ALOGE("set(): Could not get audioflinger");
115         return NO_INIT;
116     }
117 
118     if (type == NULL && uuid == NULL) {
119         ALOGW("Must specify at least type or uuid");
120         return BAD_VALUE;
121     }
122 
123     mPriority = priority;
124     mCbf = cbf;
125     mUserData = user;
126     mSessionId = sessionId;
127 
128     memset(&mDescriptor, 0, sizeof(effect_descriptor_t));
129     mDescriptor.type = *(type != NULL ? type : EFFECT_UUID_NULL);
130     mDescriptor.uuid = *(uuid != NULL ? uuid : EFFECT_UUID_NULL);
131 
132     mIEffectClient = new EffectClient(this);
133     mClientPid = IPCThreadState::self()->getCallingPid();
134 
135     iEffect = audioFlinger->createEffect((effect_descriptor_t *)&mDescriptor,
136             mIEffectClient, priority, io, mSessionId, mOpPackageName, mClientPid,
137             &mStatus, &mId, &enabled);
138 
139     if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) {
140         char typeBuffer[64], uuidBuffer[64];
141         guidToString(type, typeBuffer, sizeof(typeBuffer));
142         guidToString(uuid, uuidBuffer, sizeof(uuidBuffer));
143         ALOGE("set(): AudioFlinger could not create effect %s / %s, status: %d",
144                 typeBuffer, uuidBuffer, mStatus);
145         if (iEffect == 0) {
146             mStatus = NO_INIT;
147         }
148         return mStatus;
149     }
150 
151     mEnabled = (volatile int32_t)enabled;
152 
153     cblk = iEffect->getCblk();
154     if (cblk == 0) {
155         mStatus = NO_INIT;
156         ALOGE("Could not get control block");
157         return mStatus;
158     }
159 
160     mIEffect = iEffect;
161     mCblkMemory = cblk;
162     mCblk = static_cast<effect_param_cblk_t*>(cblk->pointer());
163     int bufOffset = ((sizeof(effect_param_cblk_t) - 1) / sizeof(int) + 1) * sizeof(int);
164     mCblk->buffer = (uint8_t *)mCblk + bufOffset;
165 
166     IInterface::asBinder(iEffect)->linkToDeath(mIEffectClient);
167     ALOGV("set() %p OK effect: %s id: %d status %d enabled %d pid %d", this, mDescriptor.name, mId,
168             mStatus, mEnabled, mClientPid);
169 
170     if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
171         AudioSystem::acquireAudioSessionId(mSessionId, mClientPid);
172     }
173 
174     return mStatus;
175 }
176 
177 
~AudioEffect()178 AudioEffect::~AudioEffect()
179 {
180     ALOGV("Destructor %p", this);
181 
182     if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
183         if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
184             AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
185         }
186         if (mIEffect != NULL) {
187             mIEffect->disconnect();
188             IInterface::asBinder(mIEffect)->unlinkToDeath(mIEffectClient);
189         }
190         mIEffect.clear();
191         mCblkMemory.clear();
192         mIEffectClient.clear();
193         IPCThreadState::self()->flushCommands();
194     }
195 }
196 
197 
initCheck() const198 status_t AudioEffect::initCheck() const
199 {
200     return mStatus;
201 }
202 
203 // -------------------------------------------------------------------------
204 
descriptor() const205 effect_descriptor_t AudioEffect::descriptor() const
206 {
207     return mDescriptor;
208 }
209 
getEnabled() const210 bool AudioEffect::getEnabled() const
211 {
212     return (mEnabled != 0);
213 }
214 
setEnabled(bool enabled)215 status_t AudioEffect::setEnabled(bool enabled)
216 {
217     if (mStatus != NO_ERROR) {
218         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
219     }
220 
221     status_t status = NO_ERROR;
222 
223     AutoMutex lock(mLock);
224     if (enabled != mEnabled) {
225         if (enabled) {
226             ALOGV("enable %p", this);
227             status = mIEffect->enable();
228         } else {
229             ALOGV("disable %p", this);
230             status = mIEffect->disable();
231         }
232         if (status == NO_ERROR) {
233             mEnabled = enabled;
234         }
235     }
236     return status;
237 }
238 
command(uint32_t cmdCode,uint32_t cmdSize,void * cmdData,uint32_t * replySize,void * replyData)239 status_t AudioEffect::command(uint32_t cmdCode,
240                               uint32_t cmdSize,
241                               void *cmdData,
242                               uint32_t *replySize,
243                               void *replyData)
244 {
245     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
246         ALOGV("command() bad status %d", mStatus);
247         return mStatus;
248     }
249 
250     if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
251         if (mEnabled == (cmdCode == EFFECT_CMD_ENABLE)) {
252             return NO_ERROR;
253         }
254         if (replySize == NULL || *replySize != sizeof(status_t) || replyData == NULL) {
255             return BAD_VALUE;
256         }
257         mLock.lock();
258     }
259 
260     status_t status = mIEffect->command(cmdCode, cmdSize, cmdData, replySize, replyData);
261 
262     if (cmdCode == EFFECT_CMD_ENABLE || cmdCode == EFFECT_CMD_DISABLE) {
263         if (status == NO_ERROR) {
264             status = *(status_t *)replyData;
265         }
266         if (status == NO_ERROR) {
267             mEnabled = (cmdCode == EFFECT_CMD_ENABLE);
268         }
269         mLock.unlock();
270     }
271 
272     return status;
273 }
274 
275 
setParameter(effect_param_t * param)276 status_t AudioEffect::setParameter(effect_param_t *param)
277 {
278     if (mStatus != NO_ERROR) {
279         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
280     }
281 
282     if (param == NULL || param->psize == 0 || param->vsize == 0) {
283         return BAD_VALUE;
284     }
285 
286     uint32_t size = sizeof(int);
287     uint32_t psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
288 
289     ALOGV("setParameter: param: %d, param2: %d", *(int *)param->data,
290             (param->psize == 8) ? *((int *)param->data + 1): -1);
291 
292     return mIEffect->command(EFFECT_CMD_SET_PARAM, sizeof (effect_param_t) + psize, param, &size,
293             &param->status);
294 }
295 
setParameterDeferred(effect_param_t * param)296 status_t AudioEffect::setParameterDeferred(effect_param_t *param)
297 {
298     if (mStatus != NO_ERROR) {
299         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
300     }
301 
302     if (param == NULL || param->psize == 0 || param->vsize == 0) {
303         return BAD_VALUE;
304     }
305 
306     Mutex::Autolock _l(mCblk->lock);
307 
308     int psize = ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) + param->vsize;
309     int size = ((sizeof(effect_param_t) + psize - 1) / sizeof(int) + 1) * sizeof(int);
310 
311     if (mCblk->clientIndex + size > EFFECT_PARAM_BUFFER_SIZE) {
312         return NO_MEMORY;
313     }
314     int *p = (int *)(mCblk->buffer + mCblk->clientIndex);
315     *p++ = size;
316     memcpy(p, param, sizeof(effect_param_t) + psize);
317     mCblk->clientIndex += size;
318 
319     return NO_ERROR;
320 }
321 
setParameterCommit()322 status_t AudioEffect::setParameterCommit()
323 {
324     if (mStatus != NO_ERROR) {
325         return (mStatus == ALREADY_EXISTS) ? (status_t) INVALID_OPERATION : mStatus;
326     }
327 
328     Mutex::Autolock _l(mCblk->lock);
329     if (mCblk->clientIndex == 0) {
330         return INVALID_OPERATION;
331     }
332     uint32_t size = 0;
333     return mIEffect->command(EFFECT_CMD_SET_PARAM_COMMIT, 0, NULL, &size, NULL);
334 }
335 
getParameter(effect_param_t * param)336 status_t AudioEffect::getParameter(effect_param_t *param)
337 {
338     if (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS) {
339         return mStatus;
340     }
341 
342     if (param == NULL || param->psize == 0 || param->vsize == 0) {
343         return BAD_VALUE;
344     }
345 
346     ALOGV("getParameter: param: %d, param2: %d", *(int *)param->data,
347             (param->psize == 8) ? *((int *)param->data + 1): -1);
348 
349     uint32_t psize = sizeof(effect_param_t) + ((param->psize - 1) / sizeof(int) + 1) * sizeof(int) +
350             param->vsize;
351 
352     return mIEffect->command(EFFECT_CMD_GET_PARAM, sizeof(effect_param_t) + param->psize, param,
353             &psize, param);
354 }
355 
356 
357 // -------------------------------------------------------------------------
358 
binderDied()359 void AudioEffect::binderDied()
360 {
361     ALOGW("IEffect died");
362     mStatus = DEAD_OBJECT;
363     if (mCbf != NULL) {
364         status_t status = DEAD_OBJECT;
365         mCbf(EVENT_ERROR, mUserData, &status);
366     }
367     mIEffect.clear();
368 }
369 
370 // -------------------------------------------------------------------------
371 
controlStatusChanged(bool controlGranted)372 void AudioEffect::controlStatusChanged(bool controlGranted)
373 {
374     ALOGV("controlStatusChanged %p control %d callback %p mUserData %p", this, controlGranted, mCbf,
375             mUserData);
376     if (controlGranted) {
377         if (mStatus == ALREADY_EXISTS) {
378             mStatus = NO_ERROR;
379         }
380     } else {
381         if (mStatus == NO_ERROR) {
382             mStatus = ALREADY_EXISTS;
383         }
384     }
385     if (mCbf != NULL) {
386         mCbf(EVENT_CONTROL_STATUS_CHANGED, mUserData, &controlGranted);
387     }
388 }
389 
enableStatusChanged(bool enabled)390 void AudioEffect::enableStatusChanged(bool enabled)
391 {
392     ALOGV("enableStatusChanged %p enabled %d mCbf %p", this, enabled, mCbf);
393     if (mStatus == ALREADY_EXISTS) {
394         mEnabled = enabled;
395         if (mCbf != NULL) {
396             mCbf(EVENT_ENABLE_STATUS_CHANGED, mUserData, &enabled);
397         }
398     }
399 }
400 
commandExecuted(uint32_t cmdCode,uint32_t cmdSize __unused,void * cmdData,uint32_t replySize __unused,void * replyData)401 void AudioEffect::commandExecuted(uint32_t cmdCode,
402                                   uint32_t cmdSize __unused,
403                                   void *cmdData,
404                                   uint32_t replySize __unused,
405                                   void *replyData)
406 {
407     if (cmdData == NULL || replyData == NULL) {
408         return;
409     }
410 
411     if (mCbf != NULL && cmdCode == EFFECT_CMD_SET_PARAM) {
412         effect_param_t *cmd = (effect_param_t *)cmdData;
413         cmd->status = *(int32_t *)replyData;
414         mCbf(EVENT_PARAMETER_CHANGED, mUserData, cmd);
415     }
416 }
417 
418 // -------------------------------------------------------------------------
419 
queryNumberEffects(uint32_t * numEffects)420 status_t AudioEffect::queryNumberEffects(uint32_t *numEffects)
421 {
422     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
423     if (af == 0) return PERMISSION_DENIED;
424     return af->queryNumberEffects(numEffects);
425 }
426 
queryEffect(uint32_t index,effect_descriptor_t * descriptor)427 status_t AudioEffect::queryEffect(uint32_t index, effect_descriptor_t *descriptor)
428 {
429     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
430     if (af == 0) return PERMISSION_DENIED;
431     return af->queryEffect(index, descriptor);
432 }
433 
getEffectDescriptor(const effect_uuid_t * uuid,const effect_uuid_t * type,uint32_t preferredTypeFlag,effect_descriptor_t * descriptor)434 status_t AudioEffect::getEffectDescriptor(const effect_uuid_t *uuid,
435                                           const effect_uuid_t *type,
436                                           uint32_t preferredTypeFlag,
437                                           effect_descriptor_t *descriptor)
438 {
439     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
440     if (af == 0) return PERMISSION_DENIED;
441     return af->getEffectDescriptor(uuid, type, preferredTypeFlag, descriptor);
442 }
443 
queryDefaultPreProcessing(audio_session_t audioSession,effect_descriptor_t * descriptors,uint32_t * count)444 status_t AudioEffect::queryDefaultPreProcessing(audio_session_t audioSession,
445                                           effect_descriptor_t *descriptors,
446                                           uint32_t *count)
447 {
448     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
449     if (aps == 0) return PERMISSION_DENIED;
450     return aps->queryDefaultPreProcessing(audioSession, descriptors, count);
451 }
452 
newEffectUniqueId(audio_unique_id_t * id)453 status_t AudioEffect::newEffectUniqueId(audio_unique_id_t* id)
454 {
455     const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
456     if (af == 0) return PERMISSION_DENIED;
457     *id = af->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
458     return NO_ERROR;
459 }
460 
addSourceDefaultEffect(const char * typeStr,const String16 & opPackageName,const char * uuidStr,int32_t priority,audio_source_t source,audio_unique_id_t * id)461 status_t AudioEffect::addSourceDefaultEffect(const char *typeStr,
462                                              const String16& opPackageName,
463                                              const char *uuidStr,
464                                              int32_t priority,
465                                              audio_source_t source,
466                                              audio_unique_id_t *id)
467 {
468     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
469     if (aps == 0) return PERMISSION_DENIED;
470 
471     if (typeStr == NULL && uuidStr == NULL) return BAD_VALUE;
472 
473     // Convert type & uuid from string to effect_uuid_t.
474     effect_uuid_t type;
475     if (typeStr != NULL) {
476         status_t res = stringToGuid(typeStr, &type);
477         if (res != OK) return res;
478     } else {
479         type = *EFFECT_UUID_NULL;
480     }
481 
482     effect_uuid_t uuid;
483     if (uuidStr != NULL) {
484         status_t res = stringToGuid(uuidStr, &uuid);
485         if (res != OK) return res;
486     } else {
487         uuid = *EFFECT_UUID_NULL;
488     }
489 
490     return aps->addSourceDefaultEffect(&type, opPackageName, &uuid, priority, source, id);
491 }
492 
addStreamDefaultEffect(const char * typeStr,const String16 & opPackageName,const char * uuidStr,int32_t priority,audio_usage_t usage,audio_unique_id_t * id)493 status_t AudioEffect::addStreamDefaultEffect(const char *typeStr,
494                                              const String16& opPackageName,
495                                              const char *uuidStr,
496                                              int32_t priority,
497                                              audio_usage_t usage,
498                                              audio_unique_id_t *id)
499 {
500     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
501     if (aps == 0) return PERMISSION_DENIED;
502 
503     if (typeStr == NULL && uuidStr == NULL) return BAD_VALUE;
504 
505     // Convert type & uuid from string to effect_uuid_t.
506     effect_uuid_t type;
507     if (typeStr != NULL) {
508         status_t res = stringToGuid(typeStr, &type);
509         if (res != OK) return res;
510     } else {
511         type = *EFFECT_UUID_NULL;
512     }
513 
514     effect_uuid_t uuid;
515     if (uuidStr != NULL) {
516         status_t res = stringToGuid(uuidStr, &uuid);
517         if (res != OK) return res;
518     } else {
519         uuid = *EFFECT_UUID_NULL;
520     }
521 
522     return aps->addStreamDefaultEffect(&type, opPackageName, &uuid, priority, usage, id);
523 }
524 
removeSourceDefaultEffect(audio_unique_id_t id)525 status_t AudioEffect::removeSourceDefaultEffect(audio_unique_id_t id)
526 {
527     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
528     if (aps == 0) return PERMISSION_DENIED;
529 
530     return aps->removeSourceDefaultEffect(id);
531 }
532 
removeStreamDefaultEffect(audio_unique_id_t id)533 status_t AudioEffect::removeStreamDefaultEffect(audio_unique_id_t id)
534 {
535     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
536     if (aps == 0) return PERMISSION_DENIED;
537 
538     return aps->removeStreamDefaultEffect(id);
539 }
540 
541 // -------------------------------------------------------------------------
542 
stringToGuid(const char * str,effect_uuid_t * guid)543 status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
544 {
545     if (str == NULL || guid == NULL) {
546         return BAD_VALUE;
547     }
548 
549     int tmp[10];
550 
551     if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
552             tmp, tmp+1, tmp+2, tmp+3, tmp+4, tmp+5, tmp+6, tmp+7, tmp+8, tmp+9) < 10) {
553         return BAD_VALUE;
554     }
555     guid->timeLow = (uint32_t)tmp[0];
556     guid->timeMid = (uint16_t)tmp[1];
557     guid->timeHiAndVersion = (uint16_t)tmp[2];
558     guid->clockSeq = (uint16_t)tmp[3];
559     guid->node[0] = (uint8_t)tmp[4];
560     guid->node[1] = (uint8_t)tmp[5];
561     guid->node[2] = (uint8_t)tmp[6];
562     guid->node[3] = (uint8_t)tmp[7];
563     guid->node[4] = (uint8_t)tmp[8];
564     guid->node[5] = (uint8_t)tmp[9];
565 
566     return NO_ERROR;
567 }
568 
guidToString(const effect_uuid_t * guid,char * str,size_t maxLen)569 status_t AudioEffect::guidToString(const effect_uuid_t *guid, char *str, size_t maxLen)
570 {
571     if (guid == NULL || str == NULL) {
572         return BAD_VALUE;
573     }
574 
575     snprintf(str, maxLen, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
576             guid->timeLow,
577             guid->timeMid,
578             guid->timeHiAndVersion,
579             guid->clockSeq,
580             guid->node[0],
581             guid->node[1],
582             guid->node[2],
583             guid->node[3],
584             guid->node[4],
585             guid->node[5]);
586 
587     return NO_ERROR;
588 }
589 
590 
591 } // namespace android
592