summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/private/media/AudioTrackShared.h5
-rw-r--r--media/libmedia/AudioRecord.cpp93
2 files changed, 44 insertions, 54 deletions
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index ac5372f..3063448 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -31,17 +31,12 @@ namespace android {
// init time
#define MAX_RUN_TIMEOUT_MS 1000
#define WAIT_PERIOD_MS 10
-// AudioTrack no longer uses this, it is for AudioRecord only:
-#define RESTORE_TIMEOUT_MS 5000 // Maximum waiting time for a track to be restored
#define CBLK_UNDERRUN 0x01 // set: underrun (out) or overrrun (in), clear: no underrun or overrun
#define CBLK_FORCEREADY 0x02 // set: track is considered ready immediately by AudioFlinger,
// clear: track is ready when buffer full
#define CBLK_INVALID 0x04 // track buffer invalidated by AudioFlinger, need to re-create
#define CBLK_DISABLED 0x08 // track disabled by AudioFlinger due to underrun, need to re-start
-// AudioTrack no longer uses these, they are for AudioRecord only:
-#define CBLK_RESTORING 0x10 // track is being restored after invalidation by AudioFlinger
-#define CBLK_RESTORED 0x20 // track has been restored after invalidation by AudioFlinger
// Important: do not add any virtual methods, including ~
struct audio_track_cblk_t
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index b40aaf5..062f546 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -300,7 +300,9 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
}
}
if (cblk->flags & CBLK_INVALID) {
- ret = restoreRecord_l(cblk);
+ audio_track_cblk_t* temp = cblk;
+ ret = restoreRecord_l(temp);
+ cblk = temp;
}
cblk->lock.unlock();
if (ret == NO_ERROR) {
@@ -431,6 +433,7 @@ status_t AudioRecord::openRecord_l(
status_t status;
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
if (audioFlinger == 0) {
+ ALOGE("Could not get audioflinger");
return NO_INIT;
}
@@ -453,19 +456,20 @@ status_t AudioRecord::openRecord_l(
ALOGE("AudioFlinger could not create record track, status: %d", status);
return status;
}
- sp<IMemory> cblk = record->getCblk();
- if (cblk == 0) {
+ sp<IMemory> iMem = record->getCblk();
+ if (iMem == 0) {
ALOGE("Could not get control block");
return NO_INIT;
}
mAudioRecord.clear();
mAudioRecord = record;
mCblkMemory.clear();
- mCblkMemory = cblk;
- mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
- mBuffers = (char*)mCblk + sizeof(audio_track_cblk_t);
- mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
- mCblk->waitTimeMs = 0;
+ mCblkMemory = iMem;
+ audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMem->pointer());
+ mCblk = cblk;
+ mBuffers = (char*)cblk + sizeof(audio_track_cblk_t);
+ cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+ cblk->waitTimeMs = 0;
return NO_ERROR;
}
@@ -498,12 +502,17 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
}
if (!(cblk->flags & CBLK_INVALID)) {
mLock.unlock();
+ // this condition is in shared memory, so if IAudioRecord and control block
+ // are replaced due to mediaserver death or IAudioRecord invalidation then
+ // cv won't be signalled, but fortunately the timeout will limit the wait
result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
cblk->lock.unlock();
mLock.lock();
if (!mActive) {
return status_t(STOPPED);
}
+ // IAudioRecord may have been re-created while mLock was unlocked
+ cblk = mCblk;
cblk->lock.lock();
}
if (cblk->flags & CBLK_INVALID) {
@@ -521,7 +530,9 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
if (result == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID, &cblk->flags);
create_new_record:
- result = AudioRecord::restoreRecord_l(cblk);
+ audio_track_cblk_t* temp = cblk;
+ result = AudioRecord::restoreRecord_l(temp);
+ cblk = temp;
}
if (result != NO_ERROR) {
ALOGW("obtainBuffer create Track error %d", result);
@@ -749,57 +760,41 @@ bool AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread)
// must be called with mLock and cblk.lock held. Callers must also hold strong references on
// the IAudioRecord and IMemory in case they are recreated here.
// If the IAudioRecord is successfully restored, the cblk pointer is updated
-status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
+status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& refCblk)
{
status_t result;
- if (!(android_atomic_or(CBLK_RESTORING, &cblk->flags) & CBLK_RESTORING)) {
- ALOGW("dead IAudioRecord, creating a new one");
- // signal old cblk condition so that other threads waiting for available buffers stop
- // waiting now
- cblk->cv.broadcast();
- cblk->lock.unlock();
+ audio_track_cblk_t* cblk = refCblk;
+ audio_track_cblk_t* newCblk = cblk;
+ ALOGW("dead IAudioRecord, creating a new one");
- // if the new IAudioRecord is created, openRecord_l() will modify the
- // following member variables: mAudioRecord, mCblkMemory and mCblk.
- // It will also delete the strong references on previous IAudioRecord and IMemory
- result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask,
- mFrameCount, getInput_l());
- if (result == NO_ERROR) {
- // callback thread or sync event hasn't changed
- result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
- }
- if (result != NO_ERROR) {
- mActive = false;
- }
+ // signal old cblk condition so that other threads waiting for available buffers stop
+ // waiting now
+ cblk->cv.broadcast();
+ cblk->lock.unlock();
- // signal old cblk condition for other threads waiting for restore completion
- android_atomic_or(CBLK_RESTORED, &cblk->flags);
- cblk->cv.broadcast();
- } else {
- if (!(cblk->flags & CBLK_RESTORED)) {
- ALOGW("dead IAudioRecord, waiting for a new one to be created");
- mLock.unlock();
- result = cblk->cv.waitRelative(cblk->lock, milliseconds(RESTORE_TIMEOUT_MS));
- cblk->lock.unlock();
- mLock.lock();
- } else {
- ALOGW("dead IAudioRecord, already restored");
- result = NO_ERROR;
- cblk->lock.unlock();
- }
- if (result != NO_ERROR || !mActive) {
- result = status_t(STOPPED);
- }
+ // if the new IAudioRecord is created, openRecord_l() will modify the
+ // following member variables: mAudioRecord, mCblkMemory and mCblk.
+ // It will also delete the strong references on previous IAudioRecord and IMemory
+ result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask,
+ mFrameCount, getInput_l());
+ if (result == NO_ERROR) {
+ newCblk = mCblk;
+ // callback thread or sync event hasn't changed
+ result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0);
+ }
+ if (result != NO_ERROR) {
+ mActive = false;
}
+
ALOGV("restoreRecord_l() status %d mActive %d cblk %p, old cblk %p flags %08x old flags %08x",
- result, mActive, mCblk, cblk, mCblk->flags, cblk->flags);
+ result, mActive, newCblk, cblk, newCblk->flags, cblk->flags);
if (result == NO_ERROR) {
// from now on we switch to the newly created cblk
- cblk = mCblk;
+ refCblk = newCblk;
}
- cblk->lock.lock();
+ newCblk->lock.lock();
ALOGW_IF(result != NO_ERROR, "restoreRecord_l() error %d", result);