static SLresult IAndroidEffect_CreateEffect(SLAndroidEffectItf self, SLInterfaceID effectImplementationId) { SL_ENTER_INTERFACE IAndroidEffect *this = (IAndroidEffect *) self; if (SL_OBJECTID_AUDIOPLAYER == IObjectToObjectID(this->mThis)) { CAudioPlayer *ap = (CAudioPlayer *)this->mThis; if (NULL != ap->mAudioTrack) { result = android_genericFx_createEffect(this, effectImplementationId, ap->mSessionId); } else { result = SL_RESULT_RESOURCE_ERROR; } } else if (SL_OBJECTID_OUTPUTMIX == IObjectToObjectID(this->mThis)) { result = android_genericFx_createEffect(this, effectImplementationId, android::AudioSystem::SESSION_OUTPUT_MIX); } else { // the interface itself is invalid because it is not attached to an AudioPlayer or // an OutputMix result = SL_RESULT_PARAMETER_INVALID; } SL_LEAVE_INTERFACE }
SLresult AcquireStrongRef(IObject *object, SLuint32 expectedObjectID) { if (NULL == object) { return SL_RESULT_PARAMETER_INVALID; } // NTH additional validity checks on address here SLresult result; object_lock_exclusive(object); SLuint32 actualObjectID = IObjectToObjectID(object); if (expectedObjectID != actualObjectID) { SL_LOGE("object %p has object ID %u but expected %u", object, actualObjectID, expectedObjectID); result = SL_RESULT_PARAMETER_INVALID; } else if (SL_OBJECT_STATE_REALIZED != object->mState) { SL_LOGE("object %p with object ID %u is not realized", object, actualObjectID); result = SL_RESULT_PRECONDITIONS_VIOLATED; } else { ++object->mStrongRefCount; result = SL_RESULT_SUCCESS; } object_unlock_exclusive(object); return result; }
void object_unlock_exclusive_attributes(IObject *thiz, unsigned attributes) #endif { #ifdef USE_DEBUG assert(pthread_equal(pthread_self(), thiz->mOwner)); assert(NULL != thiz->mFile); assert(0 != thiz->mLine); #endif int ok; // make SL object IDs be contiguous with XA object IDs SLuint32 objectID = IObjectToObjectID(thiz); SLuint32 index = objectID; if ((XA_OBJECTID_ENGINE <= index) && (index <= XA_OBJECTID_CAMERADEVICE)) { ; } else if ((SL_OBJECTID_ENGINE <= index) && (index <= SL_OBJECTID_METADATAEXTRACTOR)) { index -= SL_OBJECTID_ENGINE - XA_OBJECTID_CAMERADEVICE - 1; } else { assert(false); index = 0; } // first synchronously handle updates to attributes here, while object is still locked. // This appears to be a loop, but actually typically runs through the loop only once. unsigned asynchronous = attributes; while (attributes) { // this sequence is carefully crafted to be O(1); tread carefully when making changes unsigned bit = ctz(attributes); // ATTR_INDEX_MAX == next bit position after the last attribute assert(ATTR_INDEX_MAX > bit); // compute the entry in the handler table using object ID and bit number AttributeHandler handler = handlerTable[index][bit]; if (NULL != handler) { asynchronous &= ~(*handler)(thiz); } attributes &= ~(1 << bit); } // any remaining attributes are handled asynchronously in the sync thread if (asynchronous) { unsigned oldAttributesMask = thiz->mAttributesMask; thiz->mAttributesMask = oldAttributesMask | asynchronous; if (oldAttributesMask) { asynchronous = ATTR_NONE; } } #ifdef ANDROID // FIXME hack to safely handle a post-unlock PrefetchStatus callback and/or AudioTrack::start() slPrefetchCallback prefetchCallback = NULL; void *prefetchContext = NULL; SLuint32 prefetchEvents = SL_PREFETCHEVENT_NONE; android::sp<android::AudioTrack> audioTrack; if (SL_OBJECTID_AUDIOPLAYER == objectID) { CAudioPlayer *ap = (CAudioPlayer *) thiz; prefetchCallback = ap->mPrefetchStatus.mDeferredPrefetchCallback; prefetchContext = ap->mPrefetchStatus.mDeferredPrefetchContext; prefetchEvents = ap->mPrefetchStatus.mDeferredPrefetchEvents; ap->mPrefetchStatus.mDeferredPrefetchCallback = NULL; // clearing these next two fields is not required, but avoids stale data during debugging ap->mPrefetchStatus.mDeferredPrefetchContext = NULL; ap->mPrefetchStatus.mDeferredPrefetchEvents = SL_PREFETCHEVENT_NONE; if (ap->mDeferredStart) { audioTrack = ap->mAudioTrack; ap->mDeferredStart = false; } } #endif #ifdef USE_DEBUG memset(&thiz->mOwner, 0, sizeof(pthread_t)); thiz->mFile = file; thiz->mLine = line; #endif ok = pthread_mutex_unlock(&thiz->mMutex); assert(0 == ok); #ifdef ANDROID // FIXME call the prefetch status callback while not holding the mutex on AudioPlayer if (NULL != prefetchCallback) { // note these are synchronous by the application's thread as it is about to return from API assert(prefetchEvents != SL_PREFETCHEVENT_NONE); CAudioPlayer *ap = (CAudioPlayer *) thiz; // spec requires separate callbacks for each event if (SL_PREFETCHEVENT_STATUSCHANGE & prefetchEvents) { (*prefetchCallback)(&ap->mPrefetchStatus.mItf, prefetchContext, SL_PREFETCHEVENT_STATUSCHANGE); } if (SL_PREFETCHEVENT_FILLLEVELCHANGE & prefetchEvents) { (*prefetchCallback)(&ap->mPrefetchStatus.mItf, prefetchContext, SL_PREFETCHEVENT_FILLLEVELCHANGE); } } // call AudioTrack::start() while not holding the mutex on AudioPlayer if (audioTrack != 0) { audioTrack->start(); audioTrack.clear(); } #endif // first update to this interface since previous sync if (ATTR_NONE != asynchronous) { unsigned id = thiz->mInstanceID; if (0 != id) { --id; assert(MAX_INSTANCE > id); IEngine *thisEngine = &thiz->mEngine->mEngine; // FIXME atomic or here interface_lock_exclusive(thisEngine); thisEngine->mChangedMask |= 1 << id; interface_unlock_exclusive(thisEngine); } } }