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