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 34namespace android { 35 36// --------------------------------------------------------------------------- 37 38AudioEffect::AudioEffect(const String16& opPackageName) 39 : mStatus(NO_INIT), mOpPackageName(opPackageName) 40{ 41} 42 43 44AudioEffect::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 58AudioEffect::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 91status_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 172AudioEffect::~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 192status_t AudioEffect::initCheck() const 193{ 194 return mStatus; 195} 196 197// ------------------------------------------------------------------------- 198 199effect_descriptor_t AudioEffect::descriptor() const 200{ 201 return mDescriptor; 202} 203 204bool AudioEffect::getEnabled() const 205{ 206 return (mEnabled != 0); 207} 208 209status_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 233status_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 270status_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 290status_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 316status_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 330status_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 353void 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 366void 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 384void 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 395void 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 414status_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 421status_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 428status_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 437status_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 447status_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 473status_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