summaryrefslogtreecommitdiffstats
path: root/media/libmedia/AudioRecord.cpp
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2011-03-28 18:37:07 -0700
committerEric Laurent <elaurent@google.com>2011-04-05 12:05:41 -0700
commit38ccae2c0324daa305f3fe77d25fdf5edec0b0e1 (patch)
treec7aec92091f634a6994ed7e836a2a1ba4e22c035 /media/libmedia/AudioRecord.cpp
parent7fb4b427d5fca79c09d69b212ddca41539c215a2 (diff)
downloadframeworks_av-38ccae2c0324daa305f3fe77d25fdf5edec0b0e1.zip
frameworks_av-38ccae2c0324daa305f3fe77d25fdf5edec0b0e1.tar.gz
frameworks_av-38ccae2c0324daa305f3fe77d25fdf5edec0b0e1.tar.bz2
New fix for issue 4111672: control block flags
The first fix (commit 913af0b4) is problematic because it makes threads in mediaserver process block on the cblk mutex. This is not permitted as it can cause audio to skip or worse have a malicious application prevent all audio playback by keeping the mutex locked. The fix consists in using atomic operations when modifying the control block flags. Also fixed audio_track_cblk_t::framesReady() so that it doesn't block when called from AudioFlinger (only applies when a loop is active). Change-Id: Ibf0abb562ced3e9f64118afdd5036854bb959428
Diffstat (limited to 'media/libmedia/AudioRecord.cpp')
-rw-r--r--media/libmedia/AudioRecord.cpp21
1 files changed, 7 insertions, 14 deletions
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index cee1c75..5d74a0a 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -35,6 +35,7 @@
#include <binder/Parcel.h>
#include <binder/IPCThreadState.h>
#include <utils/Timers.h>
+#include <utils/Atomic.h>
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
@@ -299,7 +300,7 @@ status_t AudioRecord::start()
ret = mAudioRecord->start();
cblk->lock.lock();
if (ret == DEAD_OBJECT) {
- cblk->flags |= CBLK_INVALID_MSK;
+ android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
}
}
if (cblk->flags & CBLK_INVALID_MSK) {
@@ -467,7 +468,7 @@ status_t AudioRecord::openRecord_l(
mCblkMemory = cblk;
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
- mCblk->flags &= ~CBLK_DIRECTION_MSK;
+ android_atomic_and(~CBLK_DIRECTION_MSK, &mCblk->flags);
mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
return NO_ERROR;
@@ -522,7 +523,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
result = mAudioRecord->start();
cblk->lock.lock();
if (result == DEAD_OBJECT) {
- cblk->flags |= CBLK_INVALID_MSK;
+ android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
create_new_record:
result = AudioRecord::restoreRecord_l(cblk);
}
@@ -722,12 +723,8 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
// Manage overrun callback
if (mActive && (cblk->framesAvailable() == 0)) {
LOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
- AutoMutex _l(cblk->lock);
- if ((cblk->flags & CBLK_UNDERRUN_MSK) == CBLK_UNDERRUN_OFF) {
- cblk->flags |= CBLK_UNDERRUN_ON;
- cblk->lock.unlock();
+ if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) {
mCbf(EVENT_OVERRUN, mUserData, 0);
- cblk->lock.lock();
}
}
@@ -746,10 +743,8 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
{
status_t result;
- if (!(cblk->flags & CBLK_RESTORING_MSK)) {
+ if (!(android_atomic_or(CBLK_RESTORING_ON, &cblk->flags) & CBLK_RESTORING_MSK)) {
LOGW("dead IAudioRecord, creating a new one");
-
- cblk->flags |= CBLK_RESTORING_ON;
// signal old cblk condition so that other threads waiting for available buffers stop
// waiting now
cblk->cv.broadcast();
@@ -768,10 +763,8 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
}
// signal old cblk condition for other threads waiting for restore completion
- cblk->lock.lock();
- cblk->flags |= CBLK_RESTORED_MSK;
+ android_atomic_or(CBLK_RESTORED_ON, &cblk->flags);
cblk->cv.broadcast();
- cblk->lock.unlock();
} else {
if (!(cblk->flags & CBLK_RESTORED_MSK)) {
LOGW("dead IAudioRecord, waiting for a new one to be created");