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