summaryrefslogtreecommitdiffstats
path: root/media/libmedia/AudioRecord.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libmedia/AudioRecord.cpp')
-rw-r--r--media/libmedia/AudioRecord.cpp117
1 files changed, 62 insertions, 55 deletions
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 13e60a7..807f812 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -103,9 +103,10 @@ AudioRecord::~AudioRecord()
// it is looping on buffer empty condition in obtainBuffer().
// Otherwise the callback thread will never exit.
stop();
- if (mClientRecordThread != 0) {
- mClientRecordThread->requestExitAndWait();
- mClientRecordThread.clear();
+ if (mAudioRecordThread != 0) {
+ mAudioRecordThread->requestExit(); // see comment in AudioRecord.h
+ mAudioRecordThread->requestExitAndWait();
+ mAudioRecordThread.clear();
}
mAudioRecord.clear();
IPCThreadState::self()->flushCommands();
@@ -200,7 +201,8 @@ status_t AudioRecord::set(
}
if (cbf != NULL) {
- mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava);
+ mAudioRecordThread = new AudioRecordThread(*this, threadCanCallJava);
+ mAudioRecordThread->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
}
mStatus = NO_ERROR;
@@ -210,7 +212,7 @@ status_t AudioRecord::set(
mFrameCount = mCblk->frameCount;
mChannelCount = (uint8_t)channelCount;
mChannelMask = channelMask;
- mActive = 0;
+ mActive = false;
mCbf = cbf;
mNotificationFrames = notificationFrames;
mRemainingFrames = notificationFrames;
@@ -274,41 +276,19 @@ audio_source_t AudioRecord::inputSource() const
status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
{
status_t ret = NO_ERROR;
- sp<ClientRecordThread> t = mClientRecordThread;
+ sp<AudioRecordThread> t = mAudioRecordThread;
ALOGV("start, sync event %d trigger session %d", event, triggerSession);
- if (t != 0) {
- if (t->exitPending()) {
- if (t->requestExitAndWait() == WOULD_BLOCK) {
- ALOGE("AudioRecord::start called from thread");
- return WOULD_BLOCK;
- }
- }
- }
-
AutoMutex lock(mLock);
// acquire a strong reference on the IAudioRecord and IMemory so that they cannot be destroyed
// while we are accessing the cblk
sp<IAudioRecord> audioRecord = mAudioRecord;
sp<IMemory> iMem = mCblkMemory;
audio_track_cblk_t* cblk = mCblk;
- if (mActive == 0) {
- mActive = 1;
- pid_t tid;
- if (t != 0) {
- mReadyToRun = WOULD_BLOCK;
- t->run("AudioRecord", ANDROID_PRIORITY_AUDIO);
- tid = t->getTid(); // pid_t is unknown until run()
- ALOGV("getTid=%d", tid);
- if (tid == -1) {
- tid = 0;
- }
- // thread blocks in readyToRun()
- } else {
- tid = 0; // not gettid()
- }
+ if (!mActive) {
+ mActive = true;
cblk->lock.lock();
if (!(cblk->flags & CBLK_INVALID_MSK)) {
@@ -330,19 +310,14 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
AudioSystem::kSyncRecordStartTimeOutMs;
cblk->waitTimeMs = 0;
if (t != 0) {
- // thread unblocks in readyToRun() and returns NO_ERROR
- mReadyToRun = NO_ERROR;
- mCondition.signal();
+ t->resume();
} else {
mPreviousPriority = getpriority(PRIO_PROCESS, 0);
get_sched_policy(0, &mPreviousSchedulingGroup);
androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
}
} else {
- mActive = 0;
- // thread unblocks in readyToRun() and returns NO_INIT
- mReadyToRun = NO_INIT;
- mCondition.signal();
+ mActive = false;
}
}
@@ -351,20 +326,20 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession)
status_t AudioRecord::stop()
{
- sp<ClientRecordThread> t = mClientRecordThread;
+ sp<AudioRecordThread> t = mAudioRecordThread;
ALOGV("stop");
AutoMutex lock(mLock);
- if (mActive == 1) {
- mActive = 0;
+ if (mActive) {
+ mActive = false;
mCblk->cv.signal();
mAudioRecord->stop();
// the record head position will reset to 0, so if a marker is set, we need
// to activate it again
mMarkerReached = false;
if (t != 0) {
- t->requestExit();
+ t->pause();
} else {
setpriority(PRIO_PROCESS, 0, mPreviousPriority);
set_sched_policy(0, mPreviousSchedulingGroup);
@@ -376,6 +351,7 @@ status_t AudioRecord::stop()
bool AudioRecord::stopped() const
{
+ AutoMutex lock(mLock);
return !mActive;
}
@@ -493,7 +469,7 @@ status_t AudioRecord::openRecord_l(
status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
{
AutoMutex lock(mLock);
- int active;
+ bool active;
status_t result = NO_ERROR;
audio_track_cblk_t* cblk = mCblk;
uint32_t framesReq = audioBuffer->frameCount;
@@ -522,7 +498,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
cblk->lock.unlock();
mLock.lock();
- if (mActive == 0) {
+ if (!mActive) {
return status_t(STOPPED);
}
cblk->lock.lock();
@@ -671,7 +647,7 @@ ssize_t AudioRecord::read(void* buffer, size_t userSize)
// -------------------------------------------------------------------------
-bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
+bool AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread)
{
Buffer audioBuffer;
uint32_t frames = mRemainingFrames;
@@ -683,6 +659,7 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
sp<IAudioRecord> audioRecord = mAudioRecord;
sp<IMemory> iMem = mCblkMemory;
audio_track_cblk_t* cblk = mCblk;
+ bool active = mActive;
mLock.unlock();
// Manage marker callback
@@ -741,7 +718,9 @@ bool AudioRecord::processAudioBuffer(const sp<ClientRecordThread>& thread)
// Manage overrun callback
- if (mActive && (cblk->framesAvailable() == 0)) {
+ if (active && (cblk->framesAvailable() == 0)) {
+ // The value of active is stale, but we are almost sure to be active here because
+ // otherwise we would have exited when obtainBuffer returned STOPPED earlier.
ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags);
if (!(android_atomic_or(CBLK_UNDERRUN_ON, &cblk->flags) & CBLK_UNDERRUN_MSK)) {
mCbf(EVENT_OVERRUN, mUserData, 0);
@@ -798,7 +777,7 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
result = NO_ERROR;
cblk->lock.unlock();
}
- if (result != NO_ERROR || mActive == 0) {
+ if (result != NO_ERROR || !mActive) {
result = status_t(STOPPED);
}
}
@@ -818,23 +797,51 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
// =========================================================================
-AudioRecord::ClientRecordThread::ClientRecordThread(AudioRecord& receiver, bool bCanCallJava)
- : Thread(bCanCallJava), mReceiver(receiver)
+AudioRecord::AudioRecordThread::AudioRecordThread(AudioRecord& receiver, bool bCanCallJava)
+ : Thread(bCanCallJava), mReceiver(receiver), mPaused(true)
+{
+}
+
+AudioRecord::AudioRecordThread::~AudioRecordThread()
+{
+}
+
+bool AudioRecord::AudioRecordThread::threadLoop()
+{
+ {
+ AutoMutex _l(mMyLock);
+ if (mPaused) {
+ mMyCond.wait(mMyLock);
+ // caller will check for exitPending()
+ return true;
+ }
+ }
+ if (!mReceiver.processAudioBuffer(this)) {
+ pause();
+ }
+ return true;
+}
+
+void AudioRecord::AudioRecordThread::requestExit()
{
+ // must be in this order to avoid a race condition
+ Thread::requestExit();
+ resume();
}
-bool AudioRecord::ClientRecordThread::threadLoop()
+void AudioRecord::AudioRecordThread::pause()
{
- return mReceiver.processAudioBuffer(this);
+ AutoMutex _l(mMyLock);
+ mPaused = true;
}
-status_t AudioRecord::ClientRecordThread::readyToRun()
+void AudioRecord::AudioRecordThread::resume()
{
- AutoMutex(mReceiver.mLock);
- while (mReceiver.mReadyToRun == WOULD_BLOCK) {
- mReceiver.mCondition.wait(mReceiver.mLock);
+ AutoMutex _l(mMyLock);
+ if (mPaused) {
+ mPaused = false;
+ mMyCond.signal();
}
- return mReceiver.mReadyToRun;
}
// -------------------------------------------------------------------------