Merge "AudioRecord and AudioTrack client tid"
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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;
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user