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