Loading media/libaaudio/src/legacy/AudioStreamRecord.cpp +12 −4 Original line number Diff line number Diff line Loading @@ -308,11 +308,19 @@ aaudio_result_t AudioStreamRecord::release_l() { } void AudioStreamRecord::close_l() { // The callbacks are normally joined in the AudioRecord destructor. // But if another object has a reference to the AudioRecord then // it will not get deleted here. // So we should join callbacks explicitly before returning. // Unlock around the join to avoid deadlocks if the callback tries to lock. // This can happen if the callback returns AAUDIO_CALLBACK_RESULT_STOP mStreamLock.unlock(); mAudioRecord->stopAndJoinCallbacks(); mStreamLock.lock(); mAudioRecord.clear(); // Do not close mFixedBlockWriter because a data callback // thread might still be running if someone else has a reference // to mAudioRecord. // It has a unique_ptr to its buffer so it will clean up by itself. // Do not close mFixedBlockReader. It has a unique_ptr to its buffer // so it will clean up by itself. AudioStream::close_l(); } Loading media/libaaudio/src/legacy/AudioStreamTrack.cpp +11 −5 Original line number Diff line number Diff line Loading @@ -259,12 +259,18 @@ aaudio_result_t AudioStreamTrack::release_l() { } void AudioStreamTrack::close_l() { // Stop callbacks before deleting mFixedBlockReader memory. // The callbacks are normally joined in the AudioTrack destructor. // But if another object has a reference to the AudioTrack then // it will not get deleted here. // So we should join callbacks explicitly before returning. // Unlock around the join to avoid deadlocks if the callback tries to lock. // This can happen if the callback returns AAUDIO_CALLBACK_RESULT_STOP mStreamLock.unlock(); mAudioTrack->stopAndJoinCallbacks(); mStreamLock.lock(); mAudioTrack.clear(); // Do not close mFixedBlockReader because a data callback // thread might still be running if someone else has a reference // to mAudioRecord. // It has a unique_ptr to its buffer so it will clean up by itself. // Do not close mFixedBlockReader. It has a unique_ptr to its buffer // so it will clean up by itself. AudioStream::close_l(); } Loading media/libaudioclient/AudioRecord.cpp +23 −14 Original line number Diff line number Diff line Loading @@ -181,7 +181,25 @@ AudioRecord::~AudioRecord() .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)mStatus) .record(); stopAndJoinCallbacks(); // checks mStatus if (mStatus == NO_ERROR) { IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); mAudioRecord.clear(); mCblkMemory.clear(); mBufferMemory.clear(); IPCThreadState::self()->flushCommands(); ALOGV("%s(%d): releasing session id %d", __func__, mPortId, mSessionId); pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientIdentity.pid)); AudioSystem::releaseAudioSessionId(mSessionId, pid); } } void AudioRecord::stopAndJoinCallbacks() { // Prevent nullptr crash if it did not open properly. if (mStatus != NO_ERROR) return; // Make sure that callback function exits in the case where // it is looping on buffer empty condition in obtainBuffer(). // Otherwise the callback thread will never exit. Loading @@ -194,20 +212,11 @@ AudioRecord::~AudioRecord() } // No lock here: worst case we remove a NULL callback which will be a nop if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { // This may not stop all of these device callbacks! // TODO: Add some sort of protection. AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId); } IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); mAudioRecord.clear(); mCblkMemory.clear(); mBufferMemory.clear(); IPCThreadState::self()->flushCommands(); ALOGV("%s(%d): releasing session id %d", __func__, mPortId, mSessionId); pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientIdentity.pid)); AudioSystem::releaseAudioSessionId(mSessionId, pid); } } status_t AudioRecord::set( audio_source_t inputSource, uint32_t sampleRate, Loading media/libaudioclient/AudioTrack.cpp +25 −14 Original line number Diff line number Diff line Loading @@ -327,12 +327,31 @@ AudioTrack::~AudioTrack() .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)mStatus) .record(); stopAndJoinCallbacks(); // checks mStatus if (mStatus == NO_ERROR) { IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this); mAudioTrack.clear(); mCblkMemory.clear(); mSharedBuffer.clear(); IPCThreadState::self()->flushCommands(); pid_t clientPid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientIdentity.pid)); ALOGV("%s(%d), releasing session id %d from %d on behalf of %d", __func__, mPortId, mSessionId, IPCThreadState::self()->getCallingPid(), clientPid); AudioSystem::releaseAudioSessionId(mSessionId, clientPid); } } void AudioTrack::stopAndJoinCallbacks() { // Prevent nullptr crash if it did not open properly. if (mStatus != NO_ERROR) return; // Make sure that callback function exits in the case where // it is looping on buffer full condition in obtainBuffer(). // Otherwise the callback thread will never exit. stop(); if (mAudioTrackThread != 0) { if (mAudioTrackThread != 0) { // not thread safe mProxy->interrupt(); mAudioTrackThread->requestExit(); // see comment in AudioTrack.h mAudioTrackThread->requestExitAndWait(); Loading @@ -340,18 +359,10 @@ AudioTrack::~AudioTrack() } // No lock here: worst case we remove a NULL callback which will be a nop if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) { // This may not stop all of these device callbacks! // TODO: Add some sort of protection. AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId); } IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this); mAudioTrack.clear(); mCblkMemory.clear(); mSharedBuffer.clear(); IPCThreadState::self()->flushCommands(); pid_t clientPid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientIdentity.pid)); ALOGV("%s(%d), releasing session id %d from %d on behalf of %d", __func__, mPortId, mSessionId, IPCThreadState::self()->getCallingPid(), clientPid); AudioSystem::releaseAudioSessionId(mSessionId, clientPid); mDeviceCallback.clear(); } } Loading media/libaudioclient/include/media/AudioRecord.h +13 −0 Original line number Diff line number Diff line Loading @@ -303,6 +303,19 @@ public: void stop(); bool stopped() const; /* Calls stop() and then wait for all of the callbacks to return. * It is safe to call this if stop() or pause() has already been called. * * This function is called from the destructor. But since AudioRecord * is ref counted, the destructor may be called later than desired. * This can be called explicitly as part of closing an AudioRecord * if you want to be certain that callbacks have completely finished. * * This is not thread safe and should only be called from one thread, * ideally as the AudioRecord is being closed. */ void stopAndJoinCallbacks(); /* Return the sink sample rate for this record track in Hz. * If specified as zero in constructor or set(), this will be the source sample rate. * Unlike AudioTrack, the sample rate is const after initialization, so doesn't need a lock. Loading Loading
media/libaaudio/src/legacy/AudioStreamRecord.cpp +12 −4 Original line number Diff line number Diff line Loading @@ -308,11 +308,19 @@ aaudio_result_t AudioStreamRecord::release_l() { } void AudioStreamRecord::close_l() { // The callbacks are normally joined in the AudioRecord destructor. // But if another object has a reference to the AudioRecord then // it will not get deleted here. // So we should join callbacks explicitly before returning. // Unlock around the join to avoid deadlocks if the callback tries to lock. // This can happen if the callback returns AAUDIO_CALLBACK_RESULT_STOP mStreamLock.unlock(); mAudioRecord->stopAndJoinCallbacks(); mStreamLock.lock(); mAudioRecord.clear(); // Do not close mFixedBlockWriter because a data callback // thread might still be running if someone else has a reference // to mAudioRecord. // It has a unique_ptr to its buffer so it will clean up by itself. // Do not close mFixedBlockReader. It has a unique_ptr to its buffer // so it will clean up by itself. AudioStream::close_l(); } Loading
media/libaaudio/src/legacy/AudioStreamTrack.cpp +11 −5 Original line number Diff line number Diff line Loading @@ -259,12 +259,18 @@ aaudio_result_t AudioStreamTrack::release_l() { } void AudioStreamTrack::close_l() { // Stop callbacks before deleting mFixedBlockReader memory. // The callbacks are normally joined in the AudioTrack destructor. // But if another object has a reference to the AudioTrack then // it will not get deleted here. // So we should join callbacks explicitly before returning. // Unlock around the join to avoid deadlocks if the callback tries to lock. // This can happen if the callback returns AAUDIO_CALLBACK_RESULT_STOP mStreamLock.unlock(); mAudioTrack->stopAndJoinCallbacks(); mStreamLock.lock(); mAudioTrack.clear(); // Do not close mFixedBlockReader because a data callback // thread might still be running if someone else has a reference // to mAudioRecord. // It has a unique_ptr to its buffer so it will clean up by itself. // Do not close mFixedBlockReader. It has a unique_ptr to its buffer // so it will clean up by itself. AudioStream::close_l(); } Loading
media/libaudioclient/AudioRecord.cpp +23 −14 Original line number Diff line number Diff line Loading @@ -181,7 +181,25 @@ AudioRecord::~AudioRecord() .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)mStatus) .record(); stopAndJoinCallbacks(); // checks mStatus if (mStatus == NO_ERROR) { IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); mAudioRecord.clear(); mCblkMemory.clear(); mBufferMemory.clear(); IPCThreadState::self()->flushCommands(); ALOGV("%s(%d): releasing session id %d", __func__, mPortId, mSessionId); pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientIdentity.pid)); AudioSystem::releaseAudioSessionId(mSessionId, pid); } } void AudioRecord::stopAndJoinCallbacks() { // Prevent nullptr crash if it did not open properly. if (mStatus != NO_ERROR) return; // Make sure that callback function exits in the case where // it is looping on buffer empty condition in obtainBuffer(). // Otherwise the callback thread will never exit. Loading @@ -194,20 +212,11 @@ AudioRecord::~AudioRecord() } // No lock here: worst case we remove a NULL callback which will be a nop if (mDeviceCallback != 0 && mInput != AUDIO_IO_HANDLE_NONE) { // This may not stop all of these device callbacks! // TODO: Add some sort of protection. AudioSystem::removeAudioDeviceCallback(this, mInput, mPortId); } IInterface::asBinder(mAudioRecord)->unlinkToDeath(mDeathNotifier, this); mAudioRecord.clear(); mCblkMemory.clear(); mBufferMemory.clear(); IPCThreadState::self()->flushCommands(); ALOGV("%s(%d): releasing session id %d", __func__, mPortId, mSessionId); pid_t pid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientIdentity.pid)); AudioSystem::releaseAudioSessionId(mSessionId, pid); } } status_t AudioRecord::set( audio_source_t inputSource, uint32_t sampleRate, Loading
media/libaudioclient/AudioTrack.cpp +25 −14 Original line number Diff line number Diff line Loading @@ -327,12 +327,31 @@ AudioTrack::~AudioTrack() .set(AMEDIAMETRICS_PROP_STATUS, (int32_t)mStatus) .record(); stopAndJoinCallbacks(); // checks mStatus if (mStatus == NO_ERROR) { IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this); mAudioTrack.clear(); mCblkMemory.clear(); mSharedBuffer.clear(); IPCThreadState::self()->flushCommands(); pid_t clientPid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientIdentity.pid)); ALOGV("%s(%d), releasing session id %d from %d on behalf of %d", __func__, mPortId, mSessionId, IPCThreadState::self()->getCallingPid(), clientPid); AudioSystem::releaseAudioSessionId(mSessionId, clientPid); } } void AudioTrack::stopAndJoinCallbacks() { // Prevent nullptr crash if it did not open properly. if (mStatus != NO_ERROR) return; // Make sure that callback function exits in the case where // it is looping on buffer full condition in obtainBuffer(). // Otherwise the callback thread will never exit. stop(); if (mAudioTrackThread != 0) { if (mAudioTrackThread != 0) { // not thread safe mProxy->interrupt(); mAudioTrackThread->requestExit(); // see comment in AudioTrack.h mAudioTrackThread->requestExitAndWait(); Loading @@ -340,18 +359,10 @@ AudioTrack::~AudioTrack() } // No lock here: worst case we remove a NULL callback which will be a nop if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) { // This may not stop all of these device callbacks! // TODO: Add some sort of protection. AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId); } IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this); mAudioTrack.clear(); mCblkMemory.clear(); mSharedBuffer.clear(); IPCThreadState::self()->flushCommands(); pid_t clientPid = VALUE_OR_FATAL(aidl2legacy_int32_t_pid_t(mClientIdentity.pid)); ALOGV("%s(%d), releasing session id %d from %d on behalf of %d", __func__, mPortId, mSessionId, IPCThreadState::self()->getCallingPid(), clientPid); AudioSystem::releaseAudioSessionId(mSessionId, clientPid); mDeviceCallback.clear(); } } Loading
media/libaudioclient/include/media/AudioRecord.h +13 −0 Original line number Diff line number Diff line Loading @@ -303,6 +303,19 @@ public: void stop(); bool stopped() const; /* Calls stop() and then wait for all of the callbacks to return. * It is safe to call this if stop() or pause() has already been called. * * This function is called from the destructor. But since AudioRecord * is ref counted, the destructor may be called later than desired. * This can be called explicitly as part of closing an AudioRecord * if you want to be certain that callbacks have completely finished. * * This is not thread safe and should only be called from one thread, * ideally as the AudioRecord is being closed. */ void stopAndJoinCallbacks(); /* Return the sink sample rate for this record track in Hz. * If specified as zero in constructor or set(), this will be the source sample rate. * Unlike AudioTrack, the sample rate is const after initialization, so doesn't need a lock. Loading