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 ¶m->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