X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=services%2Foboeservice%2FAAudioServiceStreamBase.cpp;h=d9b87666d4c980e79f08f27124757758e5ea081f;hb=46bd7c682db5bbc048b177c52448a7999e5740ce;hp=ff0b037e526798beaf61e123693bb9e69f684893;hpb=7306d8b37c00729dc41d663a4b244a00209d537b;p=android-x86%2Fframeworks-av.git diff --git a/services/oboeservice/AAudioServiceStreamBase.cpp b/services/oboeservice/AAudioServiceStreamBase.cpp index ff0b037e52..d9b87666d4 100644 --- a/services/oboeservice/AAudioServiceStreamBase.cpp +++ b/services/oboeservice/AAudioServiceStreamBase.cpp @@ -104,6 +104,9 @@ aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest goto error; } + // This is not protected by a lock because the stream cannot be + // referenced until the service returns a handle to the client. + // So only one thread can open a stream. mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService, request, sharingMode); @@ -112,6 +115,9 @@ aaudio_result_t AAudioServiceStreamBase::open(const aaudio::AAudioStreamRequest result = AAUDIO_ERROR_UNAVAILABLE; goto error; } + // Save a weak pointer that we will use to access the endpoint. + mServiceEndpointWeak = mServiceEndpoint; + mFramesPerBurst = mServiceEndpoint->getFramesPerBurst(); copyFrom(*mServiceEndpoint); } @@ -130,15 +136,19 @@ aaudio_result_t AAudioServiceStreamBase::close() { stop(); - if (mServiceEndpoint == nullptr) { + sp endpoint = mServiceEndpointWeak.promote(); + if (endpoint == nullptr) { result = AAUDIO_ERROR_INVALID_STATE; } else { - mServiceEndpoint->unregisterStream(this); - AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance(); - mEndpointManager.closeEndpoint(mServiceEndpoint); - mServiceEndpoint.clear(); + endpoint->unregisterStream(this); + AAudioEndpointManager &endpointManager = AAudioEndpointManager::getInstance(); + endpointManager.closeEndpoint(endpoint); + + // AAudioService::closeStream() prevents two threads from closing at the same time. + mServiceEndpoint.clear(); // endpoint will hold the pointer until this method returns. } + { std::lock_guard lock(mUpMessageQueueLock); stopTimestampThread(); @@ -152,7 +162,12 @@ aaudio_result_t AAudioServiceStreamBase::close() { aaudio_result_t AAudioServiceStreamBase::startDevice() { mClientHandle = AUDIO_PORT_HANDLE_NONE; - return mServiceEndpoint->startStream(this, &mClientHandle); + sp endpoint = mServiceEndpointWeak.promote(); + if (endpoint == nullptr) { + ALOGE("%s() has no endpoint", __func__); + return AAUDIO_ERROR_INVALID_STATE; + } + return endpoint->startStream(this, &mClientHandle); } /** @@ -162,16 +177,11 @@ aaudio_result_t AAudioServiceStreamBase::startDevice() { */ aaudio_result_t AAudioServiceStreamBase::start() { aaudio_result_t result = AAUDIO_OK; + if (isRunning()) { return AAUDIO_OK; } - if (mServiceEndpoint == nullptr) { - ALOGE("AAudioServiceStreamBase::start() missing endpoint"); - result = AAUDIO_ERROR_INVALID_STATE; - goto error; - } - // Start with fresh presentation timestamps. mAtomicTimestamp.clear(); @@ -198,10 +208,6 @@ aaudio_result_t AAudioServiceStreamBase::pause() { if (!isRunning()) { return result; } - if (mServiceEndpoint == nullptr) { - ALOGE("AAudioServiceStreamShared::pause() missing endpoint"); - return AAUDIO_ERROR_INVALID_STATE; - } // Send it now because the timestamp gets rounded up when stopStream() is called below. // Also we don't need the timestamps while we are shutting down. @@ -213,7 +219,12 @@ aaudio_result_t AAudioServiceStreamBase::pause() { return result; } - result = mServiceEndpoint->stopStream(this, mClientHandle); + sp endpoint = mServiceEndpointWeak.promote(); + if (endpoint == nullptr) { + ALOGE("%s() has no endpoint", __func__); + return AAUDIO_ERROR_INVALID_STATE; + } + result = endpoint->stopStream(this, mClientHandle); if (result != AAUDIO_OK) { ALOGE("AAudioServiceStreamShared::pause() mServiceEndpoint returned %d", result); disconnect(); // TODO should we return or pause Base first? @@ -230,11 +241,6 @@ aaudio_result_t AAudioServiceStreamBase::stop() { return result; } - if (mServiceEndpoint == nullptr) { - ALOGE("AAudioServiceStreamShared::stop() missing endpoint"); - return AAUDIO_ERROR_INVALID_STATE; - } - // Send it now because the timestamp gets rounded up when stopStream() is called below. // Also we don't need the timestamps while we are shutting down. sendCurrentTimestamp(); // warning - this calls a virtual function @@ -244,8 +250,13 @@ aaudio_result_t AAudioServiceStreamBase::stop() { return result; } + sp endpoint = mServiceEndpointWeak.promote(); + if (endpoint == nullptr) { + ALOGE("%s() has no endpoint", __func__); + return AAUDIO_ERROR_INVALID_STATE; + } // TODO wait for data to be played out - result = mServiceEndpoint->stopStream(this, mClientHandle); + result = endpoint->stopStream(this, mClientHandle); if (result != AAUDIO_OK) { ALOGE("AAudioServiceStreamShared::stop() mServiceEndpoint returned %d", result); disconnect();