Loading media/libaaudio/src/client/AudioStreamInternal.cpp +18 −11 Original line number Original line Diff line number Diff line Loading @@ -241,22 +241,18 @@ error: return result; return result; } } // This must be called under mStreamLock. aaudio_result_t AudioStreamInternal::close() { aaudio_result_t AudioStreamInternal::close() { aaudio_result_t result = AAUDIO_OK; aaudio_result_t result = AAUDIO_OK; ALOGV("%s(): mServiceStreamHandle = 0x%08X", __func__, mServiceStreamHandle); ALOGV("%s(): mServiceStreamHandle = 0x%08X", __func__, mServiceStreamHandle); if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) { if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) { // Don't close a stream while it is running. // Don't close a stream while it is running. aaudio_stream_state_t currentState = getState(); aaudio_stream_state_t currentState = getState(); if (isActive()) { // Don't close a stream while it is running. Stop it first. // If DISCONNECTED then we should still try to stop in case the // error callback is still running. if (isActive() || currentState == AAUDIO_STREAM_STATE_DISCONNECTED) { requestStop(); requestStop(); aaudio_stream_state_t nextState; int64_t timeoutNanoseconds = MIN_TIMEOUT_NANOS; result = waitForStateChange(currentState, &nextState, timeoutNanoseconds); if (result != AAUDIO_OK) { ALOGW("%s() waitForStateChange() returned %d %s", __func__, result, AAudio_convertResultToText(result)); } } } setState(AAUDIO_STREAM_STATE_CLOSING); setState(AAUDIO_STREAM_STATE_CLOSING); aaudio_handle_t serviceStreamHandle = mServiceStreamHandle; aaudio_handle_t serviceStreamHandle = mServiceStreamHandle; Loading Loading @@ -357,21 +353,31 @@ int64_t AudioStreamInternal::calculateReasonableTimeout() { return calculateReasonableTimeout(getFramesPerBurst()); return calculateReasonableTimeout(getFramesPerBurst()); } } // This must be called under mStreamLock. aaudio_result_t AudioStreamInternal::stopCallback() aaudio_result_t AudioStreamInternal::stopCallback() { { if (isDataCallbackActive()) { if (isDataCallbackSet() && (isActive() || getState() == AAUDIO_STREAM_STATE_DISCONNECTED)) { mCallbackEnabled.store(false); mCallbackEnabled.store(false); return joinThread(NULL); return joinThread(NULL); // may temporarily unlock mStreamLock } else { } else { return AAUDIO_OK; return AAUDIO_OK; } } } } // This must be called under mStreamLock. aaudio_result_t AudioStreamInternal::requestStop() { aaudio_result_t AudioStreamInternal::requestStop() { aaudio_result_t result = stopCallback(); aaudio_result_t result = stopCallback(); if (result != AAUDIO_OK) { if (result != AAUDIO_OK) { return result; return result; } } // The stream may have been unlocked temporarily to let a callback finish // and the callback may have stopped the stream. // Check to make sure the stream still needs to be stopped. // See also AudioStream::safeStop(). if (!(isActive() || getState() == AAUDIO_STREAM_STATE_DISCONNECTED)) { return AAUDIO_OK; } if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { ALOGW("%s() mServiceStreamHandle invalid = 0x%08X", ALOGW("%s() mServiceStreamHandle invalid = 0x%08X", Loading Loading @@ -728,6 +734,7 @@ int32_t AudioStreamInternal::getFramesPerBurst() const { return mFramesPerBurst; return mFramesPerBurst; } } // This must be called under mStreamLock. aaudio_result_t AudioStreamInternal::joinThread(void** returnArg) { aaudio_result_t AudioStreamInternal::joinThread(void** returnArg) { return AudioStream::joinThread(returnArg, calculateReasonableTimeout(getFramesPerBurst())); return AudioStream::joinThread(returnArg, calculateReasonableTimeout(getFramesPerBurst())); } } Loading media/libaaudio/src/client/AudioStreamInternalPlay.cpp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -58,6 +58,7 @@ aaudio_result_t AudioStreamInternalPlay::open(const AudioStreamBuilder &builder) return result; return result; } } // This must be called under mStreamLock. aaudio_result_t AudioStreamInternalPlay::requestPause() aaudio_result_t AudioStreamInternalPlay::requestPause() { { aaudio_result_t result = stopCallback(); aaudio_result_t result = stopCallback(); Loading media/libaaudio/src/core/AudioStream.cpp +6 −0 Original line number Original line Diff line number Diff line Loading @@ -211,6 +211,7 @@ aaudio_result_t AudioStream::systemStopFromApp() { return result; return result; } } // This must be called under mStreamLock. aaudio_result_t AudioStream::safeStop() { aaudio_result_t AudioStream::safeStop() { switch (getState()) { switch (getState()) { Loading Loading @@ -247,6 +248,7 @@ aaudio_result_t AudioStream::safeStop() { } } aaudio_result_t AudioStream::safeClose() { aaudio_result_t AudioStream::safeClose() { // This get temporarily unlocked in the close when joining callback threads. std::lock_guard<std::mutex> lock(mStreamLock); std::lock_guard<std::mutex> lock(mStreamLock); if (collidesWithCallback()) { if (collidesWithCallback()) { ALOGE("%s cannot be called from a callback!", __func__); ALOGE("%s cannot be called from a callback!", __func__); Loading Loading @@ -363,6 +365,7 @@ aaudio_result_t AudioStream::createThread(int64_t periodNanoseconds, } } } } // This must be called under mStreamLock. aaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanoseconds __unused) aaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanoseconds __unused) { { if (!mHasThread) { if (!mHasThread) { Loading @@ -374,6 +377,8 @@ aaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanosec // then we don't need to join(). The thread is already about to exit. // then we don't need to join(). The thread is already about to exit. if (pthread_self() != mThread) { if (pthread_self() != mThread) { // Called from an app thread. Not the callback. // Called from an app thread. Not the callback. // Unlock because the callback may be trying to stop the stream but is blocked. mStreamLock.unlock(); #if 0 #if 0 // TODO implement equivalent of pthread_timedjoin_np() // TODO implement equivalent of pthread_timedjoin_np() struct timespec abstime; struct timespec abstime; Loading @@ -381,6 +386,7 @@ aaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanosec #else #else int err = pthread_join(mThread, returnArg); int err = pthread_join(mThread, returnArg); #endif #endif mStreamLock.lock(); if (err) { if (err) { ALOGE("%s() pthread_join() returns err = %d", __func__, err); ALOGE("%s() pthread_join() returns err = %d", __func__, err); result = AAudioConvert_androidToAAudioResult(-err); result = AAudioConvert_androidToAAudioResult(-err); Loading Loading
media/libaaudio/src/client/AudioStreamInternal.cpp +18 −11 Original line number Original line Diff line number Diff line Loading @@ -241,22 +241,18 @@ error: return result; return result; } } // This must be called under mStreamLock. aaudio_result_t AudioStreamInternal::close() { aaudio_result_t AudioStreamInternal::close() { aaudio_result_t result = AAUDIO_OK; aaudio_result_t result = AAUDIO_OK; ALOGV("%s(): mServiceStreamHandle = 0x%08X", __func__, mServiceStreamHandle); ALOGV("%s(): mServiceStreamHandle = 0x%08X", __func__, mServiceStreamHandle); if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) { if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) { // Don't close a stream while it is running. // Don't close a stream while it is running. aaudio_stream_state_t currentState = getState(); aaudio_stream_state_t currentState = getState(); if (isActive()) { // Don't close a stream while it is running. Stop it first. // If DISCONNECTED then we should still try to stop in case the // error callback is still running. if (isActive() || currentState == AAUDIO_STREAM_STATE_DISCONNECTED) { requestStop(); requestStop(); aaudio_stream_state_t nextState; int64_t timeoutNanoseconds = MIN_TIMEOUT_NANOS; result = waitForStateChange(currentState, &nextState, timeoutNanoseconds); if (result != AAUDIO_OK) { ALOGW("%s() waitForStateChange() returned %d %s", __func__, result, AAudio_convertResultToText(result)); } } } setState(AAUDIO_STREAM_STATE_CLOSING); setState(AAUDIO_STREAM_STATE_CLOSING); aaudio_handle_t serviceStreamHandle = mServiceStreamHandle; aaudio_handle_t serviceStreamHandle = mServiceStreamHandle; Loading Loading @@ -357,21 +353,31 @@ int64_t AudioStreamInternal::calculateReasonableTimeout() { return calculateReasonableTimeout(getFramesPerBurst()); return calculateReasonableTimeout(getFramesPerBurst()); } } // This must be called under mStreamLock. aaudio_result_t AudioStreamInternal::stopCallback() aaudio_result_t AudioStreamInternal::stopCallback() { { if (isDataCallbackActive()) { if (isDataCallbackSet() && (isActive() || getState() == AAUDIO_STREAM_STATE_DISCONNECTED)) { mCallbackEnabled.store(false); mCallbackEnabled.store(false); return joinThread(NULL); return joinThread(NULL); // may temporarily unlock mStreamLock } else { } else { return AAUDIO_OK; return AAUDIO_OK; } } } } // This must be called under mStreamLock. aaudio_result_t AudioStreamInternal::requestStop() { aaudio_result_t AudioStreamInternal::requestStop() { aaudio_result_t result = stopCallback(); aaudio_result_t result = stopCallback(); if (result != AAUDIO_OK) { if (result != AAUDIO_OK) { return result; return result; } } // The stream may have been unlocked temporarily to let a callback finish // and the callback may have stopped the stream. // Check to make sure the stream still needs to be stopped. // See also AudioStream::safeStop(). if (!(isActive() || getState() == AAUDIO_STREAM_STATE_DISCONNECTED)) { return AAUDIO_OK; } if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) { ALOGW("%s() mServiceStreamHandle invalid = 0x%08X", ALOGW("%s() mServiceStreamHandle invalid = 0x%08X", Loading Loading @@ -728,6 +734,7 @@ int32_t AudioStreamInternal::getFramesPerBurst() const { return mFramesPerBurst; return mFramesPerBurst; } } // This must be called under mStreamLock. aaudio_result_t AudioStreamInternal::joinThread(void** returnArg) { aaudio_result_t AudioStreamInternal::joinThread(void** returnArg) { return AudioStream::joinThread(returnArg, calculateReasonableTimeout(getFramesPerBurst())); return AudioStream::joinThread(returnArg, calculateReasonableTimeout(getFramesPerBurst())); } } Loading
media/libaaudio/src/client/AudioStreamInternalPlay.cpp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -58,6 +58,7 @@ aaudio_result_t AudioStreamInternalPlay::open(const AudioStreamBuilder &builder) return result; return result; } } // This must be called under mStreamLock. aaudio_result_t AudioStreamInternalPlay::requestPause() aaudio_result_t AudioStreamInternalPlay::requestPause() { { aaudio_result_t result = stopCallback(); aaudio_result_t result = stopCallback(); Loading
media/libaaudio/src/core/AudioStream.cpp +6 −0 Original line number Original line Diff line number Diff line Loading @@ -211,6 +211,7 @@ aaudio_result_t AudioStream::systemStopFromApp() { return result; return result; } } // This must be called under mStreamLock. aaudio_result_t AudioStream::safeStop() { aaudio_result_t AudioStream::safeStop() { switch (getState()) { switch (getState()) { Loading Loading @@ -247,6 +248,7 @@ aaudio_result_t AudioStream::safeStop() { } } aaudio_result_t AudioStream::safeClose() { aaudio_result_t AudioStream::safeClose() { // This get temporarily unlocked in the close when joining callback threads. std::lock_guard<std::mutex> lock(mStreamLock); std::lock_guard<std::mutex> lock(mStreamLock); if (collidesWithCallback()) { if (collidesWithCallback()) { ALOGE("%s cannot be called from a callback!", __func__); ALOGE("%s cannot be called from a callback!", __func__); Loading Loading @@ -363,6 +365,7 @@ aaudio_result_t AudioStream::createThread(int64_t periodNanoseconds, } } } } // This must be called under mStreamLock. aaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanoseconds __unused) aaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanoseconds __unused) { { if (!mHasThread) { if (!mHasThread) { Loading @@ -374,6 +377,8 @@ aaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanosec // then we don't need to join(). The thread is already about to exit. // then we don't need to join(). The thread is already about to exit. if (pthread_self() != mThread) { if (pthread_self() != mThread) { // Called from an app thread. Not the callback. // Called from an app thread. Not the callback. // Unlock because the callback may be trying to stop the stream but is blocked. mStreamLock.unlock(); #if 0 #if 0 // TODO implement equivalent of pthread_timedjoin_np() // TODO implement equivalent of pthread_timedjoin_np() struct timespec abstime; struct timespec abstime; Loading @@ -381,6 +386,7 @@ aaudio_result_t AudioStream::joinThread(void** returnArg, int64_t timeoutNanosec #else #else int err = pthread_join(mThread, returnArg); int err = pthread_join(mThread, returnArg); #endif #endif mStreamLock.lock(); if (err) { if (err) { ALOGE("%s() pthread_join() returns err = %d", __func__, err); ALOGE("%s() pthread_join() returns err = %d", __func__, err); result = AAudioConvert_androidToAAudioResult(-err); result = AAudioConvert_androidToAAudioResult(-err); Loading