Merge "AudioRecord and AudioTrack client tid"

This commit is contained in:
Glenn Kasten
2012-02-14 09:01:04 -08:00
committed by Android (Google) Code Review
9 changed files with 79 additions and 35 deletions

View File

@@ -341,7 +341,7 @@ private:
private:
friend class AudioRecord;
virtual bool threadLoop();
virtual status_t readyToRun() { return NO_ERROR; }
virtual status_t readyToRun();
virtual void onFirstRef() {}
AudioRecord& mReceiver;
};
@@ -359,7 +359,9 @@ private:
sp<IAudioRecord> mAudioRecord;
sp<IMemory> mCblkMemory;
sp<ClientRecordThread> mClientRecordThread;
status_t mReadyToRun;
Mutex mLock;
Condition mCondition;
uint32_t mFrameCount;

View File

@@ -37,8 +37,9 @@ public:
/* After it's created the track is not active. Call start() to
* make it active. If set, the callback will start being called.
* tid identifies the client callback thread, or 0 if not needed.
*/
virtual status_t start() = 0;
virtual status_t start(pid_t tid) = 0;
/* Stop a track. If set, the callback will cease being called and
* obtainBuffer will return an error. Buffers that are already released

View File

@@ -40,8 +40,9 @@ public:
/* After it's created the track is not active. Call start() to
* make it active. If set, the callback will start being called.
* tid identifies the client callback thread, or 0 if not needed.
*/
virtual status_t start() = 0;
virtual status_t start(pid_t tid) = 0;
/* Stop a track. If set, the callback will cease being called and
* obtainBuffer will return an error. Buffers that are already released

View File

@@ -304,10 +304,25 @@ status_t AudioRecord::start()
if (mActive == 0) {
mActive = 1;
pid_t tid;
if (t != 0) {
mReadyToRun = WOULD_BLOCK;
t->run("ClientRecordThread", 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()
}
cblk->lock.lock();
if (!(cblk->flags & CBLK_INVALID_MSK)) {
cblk->lock.unlock();
ret = mAudioRecord->start();
ALOGV("mAudioRecord->start(tid=%d)", tid);
ret = mAudioRecord->start(tid);
cblk->lock.lock();
if (ret == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -322,7 +337,9 @@ status_t AudioRecord::start()
cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
cblk->waitTimeMs = 0;
if (t != 0) {
t->run("ClientRecordThread", ANDROID_PRIORITY_AUDIO);
// thread unblocks in readyToRun() and returns NO_ERROR
mReadyToRun = NO_ERROR;
mCondition.signal();
} else {
mPreviousPriority = getpriority(PRIO_PROCESS, 0);
mPreviousSchedulingGroup = androidGetThreadSchedulingGroup(0);
@@ -330,6 +347,9 @@ status_t AudioRecord::start()
}
} else {
mActive = 0;
// thread unblocks in readyToRun() and returns NO_INIT
mReadyToRun = NO_INIT;
mCondition.signal();
}
}
@@ -522,7 +542,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
ALOGW( "obtainBuffer timed out (is the CPU pegged?) "
"user=%08x, server=%08x", cblk->user, cblk->server);
cblk->lock.unlock();
result = mAudioRecord->start();
result = mAudioRecord->start(0); // callback thread hasn't changed
cblk->lock.lock();
if (result == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -760,7 +780,7 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk)
result = openRecord_l(cblk->sampleRate, mFormat, mChannelMask,
mFrameCount, mFlags, getInput_l());
if (result == NO_ERROR) {
result = mAudioRecord->start();
result = mAudioRecord->start(0); // callback thread hasn't changed
}
if (result != NO_ERROR) {
mActive = false;
@@ -811,6 +831,15 @@ bool AudioRecord::ClientRecordThread::threadLoop()
return mReceiver.processAudioBuffer(this);
}
status_t AudioRecord::ClientRecordThread::readyToRun()
{
AutoMutex(mReceiver.mLock);
while (mReceiver.mReadyToRun == WOULD_BLOCK) {
mReceiver.mCondition.wait(mReceiver.mLock);
}
return mReceiver.mReadyToRun;
}
// -------------------------------------------------------------------------
}; // namespace android

View File

@@ -362,18 +362,26 @@ void AudioTrack::start()
cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
cblk->waitTimeMs = 0;
android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
pid_t tid;
if (t != 0) {
t->run("AudioTrackThread", ANDROID_PRIORITY_AUDIO);
tid = t->getTid(); // pid_t is unknown until run()
ALOGV("getTid=%d", tid);
if (tid == -1) {
tid = 0;
}
} else {
mPreviousPriority = getpriority(PRIO_PROCESS, 0);
mPreviousSchedulingGroup = androidGetThreadSchedulingGroup(0);
androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
tid = 0; // not gettid()
}
ALOGV("start %p before lock cblk %p", this, mCblk);
if (!(cblk->flags & CBLK_INVALID_MSK)) {
cblk->lock.unlock();
status = mAudioTrack->start();
ALOGV("mAudioTrack->start(tid=%d)", tid);
status = mAudioTrack->start(tid);
cblk->lock.lock();
if (status == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -895,7 +903,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
"user=%08x, server=%08x", this, cblk->user, cblk->server);
//unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
cblk->lock.unlock();
result = mAudioTrack->start();
result = mAudioTrack->start(0); // callback thread hasn't changed
cblk->lock.lock();
if (result == DEAD_OBJECT) {
android_atomic_or(CBLK_INVALID_ON, &cblk->flags);
@@ -927,7 +935,7 @@ create_new_track:
if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) {
android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
ALOGW("obtainBuffer() track %p disabled, restarting", this);
mAudioTrack->start();
mAudioTrack->start(0); // callback thread hasn't changed
}
cblk->waitTimeMs = 0;
@@ -1218,7 +1226,7 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart)
}
}
if (mActive) {
result = mAudioTrack->start();
result = mAudioTrack->start(0); // callback thread hasn't changed
ALOGW_IF(result != NO_ERROR, "restoreTrack_l() start() failed status %d", result);
}
if (fromStart && result == NO_ERROR) {

View File

@@ -42,10 +42,11 @@ public:
{
}
virtual status_t start()
virtual status_t start(pid_t tid)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
data.writeInt32(tid);
status_t status = remote()->transact(START, data, &reply);
if (status == NO_ERROR) {
status = reply.readInt32();
@@ -90,7 +91,7 @@ status_t BnAudioRecord::onTransact(
} break;
case START: {
CHECK_INTERFACE(IAudioRecord, data, reply);
reply->writeInt32(start());
reply->writeInt32(start(data.readInt32()));
return NO_ERROR;
} break;
case STOP: {

View File

@@ -58,10 +58,11 @@ public:
return cblk;
}
virtual status_t start()
virtual status_t start(pid_t tid)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
data.writeInt32(tid);
status_t status = remote()->transact(START, data, &reply);
if (status == NO_ERROR) {
status = reply.readInt32();
@@ -130,7 +131,7 @@ status_t BnAudioTrack::onTransact(
} break;
case START: {
CHECK_INTERFACE(IAudioTrack, data, reply);
reply->writeInt32(start());
reply->writeInt32(start(data.readInt32()));
return NO_ERROR;
} break;
case STOP: {

View File

@@ -3494,11 +3494,11 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const {
return false;
}
status_t AudioFlinger::PlaybackThread::Track::start()
status_t AudioFlinger::PlaybackThread::Track::start(pid_t tid)
{
status_t status = NO_ERROR;
ALOGV("start(%d), calling pid %d session %d",
mName, IPCThreadState::self()->getCallingPid(), mSessionId);
ALOGV("start(%d), calling pid %d session %d tid %d",
mName, IPCThreadState::self()->getCallingPid(), mSessionId, tid);
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
Mutex::Autolock _l(thread->mLock);
@@ -3717,12 +3717,12 @@ getNextBuffer_exit:
return NOT_ENOUGH_DATA;
}
status_t AudioFlinger::RecordThread::RecordTrack::start()
status_t AudioFlinger::RecordThread::RecordTrack::start(pid_t tid)
{
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
RecordThread *recordThread = (RecordThread *)thread.get();
return recordThread->start(this);
return recordThread->start(this, tid);
} else {
return BAD_VALUE;
}
@@ -3789,9 +3789,9 @@ AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
clearBufferQueue();
}
status_t AudioFlinger::PlaybackThread::OutputTrack::start()
status_t AudioFlinger::PlaybackThread::OutputTrack::start(pid_t tid)
{
status_t status = Track::start();
status_t status = Track::start(tid);
if (status != NO_ERROR) {
return status;
}
@@ -3821,7 +3821,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr
uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs();
if (!mActive && frames != 0) {
start();
start(0);
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
MixerThread *mixerThread = (MixerThread *)thread.get();
@@ -4056,8 +4056,8 @@ sp<IMemory> AudioFlinger::TrackHandle::getCblk() const {
return mTrack->getCblk();
}
status_t AudioFlinger::TrackHandle::start() {
return mTrack->start();
status_t AudioFlinger::TrackHandle::start(pid_t tid) {
return mTrack->start(tid);
}
void AudioFlinger::TrackHandle::stop() {
@@ -4179,9 +4179,9 @@ sp<IMemory> AudioFlinger::RecordHandle::getCblk() const {
return mRecordTrack->getCblk();
}
status_t AudioFlinger::RecordHandle::start() {
status_t AudioFlinger::RecordHandle::start(pid_t tid) {
ALOGV("RecordHandle::start()");
return mRecordTrack->start();
return mRecordTrack->start(tid);
}
void AudioFlinger::RecordHandle::stop() {
@@ -4473,9 +4473,9 @@ Exit:
return track;
}
status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack, pid_t tid)
{
ALOGV("RecordThread::start");
ALOGV("RecordThread::start tid=%d", tid);
sp <ThreadBase> strongMe = this;
status_t status = NO_ERROR;
{

View File

@@ -314,7 +314,7 @@ private:
int sessionId);
virtual ~TrackBase();
virtual status_t start() = 0;
virtual status_t start(pid_t tid) = 0;
virtual void stop() = 0;
sp<IMemory> getCblk() const { return mCblkMemory; }
audio_track_cblk_t* cblk() const { return mCblk; }
@@ -586,7 +586,7 @@ private:
virtual ~Track();
void dump(char* buffer, size_t size);
virtual status_t start();
virtual status_t start(pid_t tid);
virtual void stop();
void pause();
@@ -668,7 +668,7 @@ private:
int frameCount);
virtual ~OutputTrack();
virtual status_t start();
virtual status_t start(pid_t tid);
virtual void stop();
bool write(int16_t* data, uint32_t frames);
bool bufferQueueEmpty() const { return (mBufferQueue.size() == 0) ? true : false; }
@@ -905,7 +905,7 @@ private:
TrackHandle(const sp<PlaybackThread::Track>& track);
virtual ~TrackHandle();
virtual sp<IMemory> getCblk() const;
virtual status_t start();
virtual status_t start(pid_t tid);
virtual void stop();
virtual void flush();
virtual void mute(bool);
@@ -943,7 +943,7 @@ private:
int sessionId);
virtual ~RecordTrack();
virtual status_t start();
virtual status_t start(pid_t tid);
virtual void stop();
bool overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
@@ -988,6 +988,7 @@ private:
status_t *status);
status_t start(RecordTrack* recordTrack);
status_t start(RecordTrack* recordTrack, pid_t tid);
void stop(RecordTrack* recordTrack);
status_t dump(int fd, const Vector<String16>& args);
AudioStreamIn* getInput() const;
@@ -1028,7 +1029,7 @@ private:
RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack);
virtual ~RecordHandle();
virtual sp<IMemory> getCblk() const;
virtual status_t start();
virtual status_t start(pid_t tid);
virtual void stop();
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);