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