From 3acbd053c842e76e1a40fc8a0bf62de87eebf00f Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 28 Feb 2012 10:39:56 -0800 Subject: Configure policy of mediaserver threads Change-Id: Ifd825590ba36996064a458f64453a94b84722cb0 --- include/media/AudioTrack.h | 14 +++- include/media/IAudioFlinger.h | 1 + include/media/IAudioRecord.h | 5 +- include/media/IAudioTrack.h | 5 +- include/private/media/AudioTrackShared.h | 1 + media/libmedia/AudioRecord.cpp | 8 +-- media/libmedia/AudioTrack.cpp | 113 ++++++++++++++++++++++--------- media/libmedia/IAudioFlinger.cpp | 5 +- media/libmedia/IAudioRecord.cpp | 6 +- media/libmedia/IAudioTrack.cpp | 5 +- services/audioflinger/Android.mk | 2 + services/audioflinger/AudioFlinger.cpp | 57 +++++++++------- services/audioflinger/AudioFlinger.h | 20 +++--- 13 files changed, 154 insertions(+), 88 deletions(-) diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index 4906bd3..98b1f3e 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -138,7 +138,7 @@ public: * frameCount: Minimum size of track PCM buffer in frames. This defines the * latency of the track. The actual size selected by the AudioTrack could be * larger if the requested size is not compatible with current audio HAL - * latency. + * latency. Zero means to use a default value. * flags: See comments on audio_output_flags_t in . * cbf: Callback function. If not null, this function is called periodically * to request new PCM data. @@ -460,12 +460,24 @@ protected: { public: AudioTrackThread(AudioTrack& receiver, bool bCanCallJava = false); + + // Do not call Thread::requestExitAndWait() without first calling requestExit(). + // Thread::requestExitAndWait() is not virtual, and the implementation doesn't do enough. + virtual void requestExit(); + + void pause(); // suspend thread from execution at next loop boundary + void resume(); // allow thread to execute, if not requested to exit + private: friend class AudioTrack; virtual bool threadLoop(); virtual status_t readyToRun(); virtual void onFirstRef(); AudioTrack& mReceiver; + ~AudioTrackThread(); + Mutex mMyLock; // Thread::mLock is private + Condition mMyCond; // Thread::mThreadExitedCondition is private + bool mPaused; // whether thread is currently paused }; // body of AudioTrackThread::threadLoop() diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index 04ac3ee..86e228b 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -65,6 +65,7 @@ public: track_flags_t flags, const sp& sharedBuffer, audio_io_handle_t output, + pid_t tid, // -1 means unused, otherwise must be valid non-0 int *sessionId, status_t *status) = 0; diff --git a/include/media/IAudioRecord.h b/include/media/IAudioRecord.h index c486c6b..ebc03ea 100644 --- a/include/media/IAudioRecord.h +++ b/include/media/IAudioRecord.h @@ -35,10 +35,9 @@ public: DECLARE_META_INTERFACE(AudioRecord); /* 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. + * make it active. */ - virtual status_t start(pid_t tid, int event, int triggerSession) = 0; + virtual status_t start(int event, int triggerSession) = 0; /* Stop a track. If set, the callback will cease being called and * obtainBuffer will return an error. Buffers that are already released diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h index 577b095..9e0e389 100644 --- a/include/media/IAudioTrack.h +++ b/include/media/IAudioTrack.h @@ -39,10 +39,9 @@ public: virtual sp getCblk() const = 0; /* 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. + * make it active. */ - virtual status_t start(pid_t tid) = 0; + virtual status_t start() = 0; /* Stop a track. If set, the callback will cease being called and * obtainBuffer will return an error. Buffers that are already released diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index af2db93..469f5ff 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -53,6 +53,7 @@ namespace android { #define CBLK_RESTORED_MSK 0x0040 #define CBLK_RESTORED_ON 0x0040 // track has been restored after invalidation #define CBLK_RESTORED_OFF 0x0040 // by AudioFlinger +#define CBLK_FAST 0x0080 // AudioFlinger successfully created a fast track // 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 1fdc536..950f5c6 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -321,8 +321,8 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession) cblk->lock.lock(); if (!(cblk->flags & CBLK_INVALID_MSK)) { cblk->lock.unlock(); - ALOGV("mAudioRecord->start(tid=%d)", tid); - ret = mAudioRecord->start(tid, event, triggerSession); + ALOGV("mAudioRecord->start()"); + ret = mAudioRecord->start(event, triggerSession); cblk->lock.lock(); if (ret == DEAD_OBJECT) { android_atomic_or(CBLK_INVALID_ON, &cblk->flags); @@ -542,7 +542,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) "user=%08x, server=%08x", cblk->user, cblk->server); cblk->lock.unlock(); // callback thread or sync event hasn't changed - result = mAudioRecord->start(0, AudioSystem::SYNC_EVENT_SAME, 0); + result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0); cblk->lock.lock(); if (result == DEAD_OBJECT) { android_atomic_or(CBLK_INVALID_ON, &cblk->flags); @@ -781,7 +781,7 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& cblk) mFrameCount, getInput_l()); if (result == NO_ERROR) { // callback thread or sync event hasn't changed - result = mAudioRecord->start(0, AudioSystem::SYNC_EVENT_SAME, 0); + result = mAudioRecord->start(AudioSystem::SYNC_EVENT_SAME, 0); } if (result != NO_ERROR) { mActive = false; diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 25d79d6..9d338f3 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -73,6 +73,8 @@ status_t AudioTrack::getMinFrameCount( *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount : afFrameCount * minBufCount * sampleRate / afSampleRate; + ALOGV("getMinFrameCount=%d: afFrameCount=%d, minBufCount=%d, afSampleRate=%d, afLatency=%d", + *frameCount, afFrameCount, minBufCount, afSampleRate, afLatency); return NO_ERROR; } @@ -159,6 +161,7 @@ AudioTrack::~AudioTrack() // Otherwise the callback thread will never exit. stop(); if (mAudioTrackThread != 0) { + mAudioTrackThread->requestExit(); // see comment in AudioTrack.h mAudioTrackThread->requestExitAndWait(); mAudioTrackThread.clear(); } @@ -223,6 +226,7 @@ status_t AudioTrack::set( // force direct flag if format is not linear PCM if (!audio_is_linear_pcm(format)) { flags = (audio_output_flags_t) + // FIXME why can't we allow direct AND fast? ((flags | AUDIO_OUTPUT_FLAG_DIRECT) & ~AUDIO_OUTPUT_FLAG_FAST); } // only allow deep buffering for music stream type @@ -255,6 +259,11 @@ status_t AudioTrack::set( mAuxEffectId = 0; mCbf = cbf; + if (cbf != NULL) { + mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava); + mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/); + } + // create the IAudioTrack status_t status = createTrack_l(streamType, sampleRate, @@ -266,13 +275,13 @@ status_t AudioTrack::set( output); if (status != NO_ERROR) { + if (mAudioTrackThread != 0) { + mAudioTrackThread->requestExit(); + mAudioTrackThread.clear(); + } return status; } - if (cbf != NULL) { - mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava); - } - mStatus = NO_ERROR; mStreamType = streamType; @@ -349,14 +358,6 @@ void AudioTrack::start() status_t status = NO_ERROR; ALOGV("start %p", this); - if (t != 0) { - if (t->exitPending()) { - if (t->requestExitAndWait() == WOULD_BLOCK) { - ALOGE("AudioTrack::start called from thread"); - return; - } - } - } AutoMutex lock(mLock); // acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed @@ -373,26 +374,19 @@ 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("AudioTrack", ANDROID_PRIORITY_AUDIO); - tid = t->getTid(); // pid_t is unknown until run() - ALOGV("getTid=%d", tid); - if (tid == -1) { - tid = 0; - } + t->resume(); } 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(); - ALOGV("mAudioTrack->start(tid=%d)", tid); - status = mAudioTrack->start(tid); + ALOGV("mAudioTrack->start()"); + status = mAudioTrack->start(); cblk->lock.lock(); if (status == DEAD_OBJECT) { android_atomic_or(CBLK_INVALID_ON, &cblk->flags); @@ -406,7 +400,7 @@ void AudioTrack::start() ALOGV("start() failed"); mActive = false; if (t != 0) { - t->requestExit(); + t->pause(); } else { setpriority(PRIO_PROCESS, 0, mPreviousPriority); androidSetThreadSchedulingGroup(0, mPreviousSchedulingGroup); @@ -439,7 +433,7 @@ void AudioTrack::stop() flush_l(); } if (t != 0) { - t->requestExit(); + t->pause(); } else { setpriority(PRIO_PROCESS, 0, mPreviousPriority); androidSetThreadSchedulingGroup(0, mPreviousSchedulingGroup); @@ -771,7 +765,7 @@ status_t AudioTrack::createTrack_l( (sharedBuffer != 0) || // use case 2: callback handler (mCbf != NULL))) { - ALOGW("AUDIO_OUTPUT_FLAG_FAST denied"); + ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client"); flags = (audio_output_flags_t) (flags & ~AUDIO_OUTPUT_FLAG_FAST); } ALOGV("createTrack_l() output %d afFrameCount %d afLatency %d", output, afFrameCount, afLatency); @@ -787,6 +781,13 @@ status_t AudioTrack::createTrack_l( if (minBufCount < 2) minBufCount = 2; int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate; + ALOGV("minFrameCount: %d, afFrameCount=%d, minBufCount=%d, sampleRate=%d, afSampleRate=%d" + ", afLatency=%d", + minFrameCount, afFrameCount, minBufCount, sampleRate, afSampleRate, afLatency); +#define MIN_FRAME_COUNT_FAST 128 // FIXME hard-coded + if ((flags & AUDIO_OUTPUT_FLAG_FAST) && (minFrameCount > MIN_FRAME_COUNT_FAST)) { + minFrameCount = MIN_FRAME_COUNT_FAST; + } if (sharedBuffer == 0) { if (frameCount == 0) { @@ -800,7 +801,7 @@ status_t AudioTrack::createTrack_l( if (mNotificationFramesAct > (uint32_t)frameCount/2) { mNotificationFramesAct = frameCount/2; } - if (frameCount < minFrameCount && !(flags & AUDIO_OUTPUT_FLAG_FAST)) { + if (frameCount < minFrameCount) { // not ALOGW because it happens all the time when playing key clicks over A2DP ALOGV("Minimum buffer size corrected from %d to %d", frameCount, minFrameCount); @@ -821,8 +822,13 @@ status_t AudioTrack::createTrack_l( if (mIsTimed) { trackFlags |= IAudioFlinger::TRACK_TIMED; } + + pid_t tid = -1; if (flags & AUDIO_OUTPUT_FLAG_FAST) { trackFlags |= IAudioFlinger::TRACK_FAST; + if (mAudioTrackThread != 0) { + tid = mAudioTrackThread->getTid(); + } } sp track = audioFlinger->createTrack(getpid(), @@ -834,6 +840,7 @@ status_t AudioTrack::createTrack_l( trackFlags, sharedBuffer, output, + tid, &mSessionId, &status); @@ -849,7 +856,15 @@ status_t AudioTrack::createTrack_l( mAudioTrack = track; mCblkMemory = cblk; mCblk = static_cast(cblk->pointer()); - android_atomic_or(CBLK_DIRECTION_OUT, &mCblk->flags); + // old has the previous value of mCblk->flags before the "or" operation + int32_t old = android_atomic_or(CBLK_DIRECTION_OUT, &mCblk->flags); + if (flags & AUDIO_OUTPUT_FLAG_FAST) { + if (old & CBLK_FAST) { + ALOGI("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", mCblk->frameCount); + } else { + ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %u", mCblk->frameCount); + } + } if (sharedBuffer == 0) { mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); } else { @@ -926,7 +941,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(0); // callback thread hasn't changed + result = mAudioTrack->start(); cblk->lock.lock(); if (result == DEAD_OBJECT) { android_atomic_or(CBLK_INVALID_ON, &cblk->flags); @@ -958,7 +973,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(0); // callback thread hasn't changed + mAudioTrack->start(); } cblk->waitTimeMs = 0; @@ -1096,7 +1111,7 @@ status_t TimedAudioTrack::queueTimedBuffer(const sp& buffer, if (mActive && (mCblk->flags & CBLK_DISABLED_MSK)) { android_atomic_and(~CBLK_DISABLED_ON, &mCblk->flags); ALOGW("queueTimedBuffer() track %p disabled, restarting", this); - mAudioTrack->start(0); + mAudioTrack->start(); } return mAudioTrack->queueTimedBuffer(buffer, pts); @@ -1301,7 +1316,7 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart) } } if (mActive) { - result = mAudioTrack->start(0); // callback thread hasn't changed + result = mAudioTrack->start(); ALOGW_IF(result != NO_ERROR, "restoreTrack_l() start() failed status %d", result); } if (fromStart && result == NO_ERROR) { @@ -1369,12 +1384,24 @@ status_t AudioTrack::dump(int fd, const Vector& args) const // ========================================================================= AudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava) - : Thread(bCanCallJava), mReceiver(receiver) + : Thread(bCanCallJava), mReceiver(receiver), mPaused(true) +{ +} + +AudioTrack::AudioTrackThread::~AudioTrackThread() { } bool AudioTrack::AudioTrackThread::threadLoop() { + { + AutoMutex _l(mMyLock); + if (mPaused) { + mMyCond.wait(mMyLock); + // caller will check for exitPending() + return true; + } + } return mReceiver.processAudioBuffer(this); } @@ -1387,6 +1414,28 @@ void AudioTrack::AudioTrackThread::onFirstRef() { } +void AudioTrack::AudioTrackThread::requestExit() +{ + // must be in this order to avoid a race condition + Thread::requestExit(); + mMyCond.signal(); +} + +void AudioTrack::AudioTrackThread::pause() +{ + AutoMutex _l(mMyLock); + mPaused = true; +} + +void AudioTrack::AudioTrackThread::resume() +{ + AutoMutex _l(mMyLock); + if (mPaused) { + mPaused = false; + mMyCond.signal(); + } +} + // ========================================================================= diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 2b5126f..e8dd438 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -91,6 +91,7 @@ public: track_flags_t flags, const sp& sharedBuffer, audio_io_handle_t output, + pid_t tid, int *sessionId, status_t *status) { @@ -106,6 +107,7 @@ public: data.writeInt32((int32_t) flags); data.writeStrongBinder(sharedBuffer->asBinder()); data.writeInt32((int32_t) output); + data.writeInt32((int32_t) tid); int lSessionId = 0; if (sessionId != NULL) { lSessionId = *sessionId; @@ -701,11 +703,12 @@ status_t BnAudioFlinger::onTransact( track_flags_t flags = (track_flags_t) data.readInt32(); sp buffer = interface_cast(data.readStrongBinder()); audio_io_handle_t output = (audio_io_handle_t) data.readInt32(); + pid_t tid = (pid_t) data.readInt32(); int sessionId = data.readInt32(); status_t status; sp track = createTrack(pid, (audio_stream_type_t) streamType, sampleRate, format, - channelCount, bufferCount, flags, buffer, output, &sessionId, &status); + channelCount, bufferCount, flags, buffer, output, tid, &sessionId, &status); reply->writeInt32(sessionId); reply->writeInt32(status); reply->writeStrongBinder(track->asBinder()); diff --git a/media/libmedia/IAudioRecord.cpp b/media/libmedia/IAudioRecord.cpp index 58c6d38..57a80a9 100644 --- a/media/libmedia/IAudioRecord.cpp +++ b/media/libmedia/IAudioRecord.cpp @@ -42,11 +42,10 @@ public: { } - virtual status_t start(pid_t tid, int event, int triggerSession) + virtual status_t start(int event, int triggerSession) { Parcel data, reply; data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor()); - data.writeInt32(tid); data.writeInt32(event); data.writeInt32(triggerSession); status_t status = remote()->transact(START, data, &reply); @@ -93,10 +92,9 @@ status_t BnAudioRecord::onTransact( } break; case START: { CHECK_INTERFACE(IAudioRecord, data, reply); - pid_t tid = (pid_t) data.readInt32(); int event = data.readInt32(); int triggerSession = data.readInt32(); - reply->writeInt32(start(tid, event, triggerSession)); + reply->writeInt32(start(event, triggerSession)); return NO_ERROR; } break; case STOP: { diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp index 09f31a7..867d1a5 100644 --- a/media/libmedia/IAudioTrack.cpp +++ b/media/libmedia/IAudioTrack.cpp @@ -61,11 +61,10 @@ public: return cblk; } - virtual status_t start(pid_t tid) + virtual status_t start() { 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(); @@ -180,7 +179,7 @@ status_t BnAudioTrack::onTransact( } break; case START: { CHECK_INTERFACE(IAudioTrack, data, reply); - reply->writeInt32(start(data.readInt32())); + reply->writeInt32(start()); return NO_ERROR; } break; case STOP: { diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk index 4667649..7202b8b 100644 --- a/services/audioflinger/Android.mk +++ b/services/audioflinger/Android.mk @@ -68,4 +68,6 @@ LOCAL_CFLAGS += -DFAST_MIXER_STATISTICS LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"' +LOCAL_CFLAGS += -UHAVE_REQUEST_PRIORITY + include $(BUILD_SHARED_LIBRARY) diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index bce30d7..865051f 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -401,6 +401,7 @@ sp AudioFlinger::createTrack( IAudioFlinger::track_flags_t flags, const sp& sharedBuffer, audio_io_handle_t output, + pid_t tid, int *sessionId, status_t *status) { @@ -458,9 +459,8 @@ sp AudioFlinger::createTrack( } ALOGV("createTrack() lSessionId: %d", lSessionId); - bool isTimed = (flags & IAudioFlinger::TRACK_TIMED) != 0; track = thread->createTrack_l(client, streamType, sampleRate, format, - channelMask, frameCount, sharedBuffer, lSessionId, flags, &lStatus); + channelMask, frameCount, sharedBuffer, lSessionId, flags, tid, &lStatus); // move effect chain to this output thread if an effect on same session was waiting // for a track to be created @@ -1569,6 +1569,7 @@ sp AudioFlinger::PlaybackThread::createTrac const sp& sharedBuffer, int sessionId, IAudioFlinger::track_flags_t flags, + pid_t tid, status_t *status) { sp track; @@ -1589,7 +1590,7 @@ sp AudioFlinger::PlaybackThread::createTrac ) || // use case 2: callback handler and small power-of-2 frame count ( - // unfortunately we can't verify that there's a callback until start() + (tid != -1) && // FIXME supported frame counts should not be hard-coded ( (frameCount == 128) || @@ -1678,6 +1679,20 @@ sp AudioFlinger::PlaybackThread::createTrac chain->incTrackCnt(); } } + +#ifdef HAVE_REQUEST_PRIORITY + if ((flags & IAudioFlinger::TRACK_FAST) && (tid != -1)) { + pid_t callingPid = IPCThreadState::self()->getCallingPid(); + // we don't have CAP_SYS_NICE, nor do we want to have it as it's too powerful, + // so ask activity manager to do this on our behalf + int err = requestPriority(callingPid, tid, 1); + if (err != 0) { + ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; error %d", + 1, callingPid, tid, err); + } + } +#endif + lStatus = NO_ERROR; Exit: @@ -3681,20 +3696,11 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const { return false; } -status_t AudioFlinger::PlaybackThread::Track::start(pid_t tid, - AudioSystem::sync_event_t event, +status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event, int triggerSession) { status_t status = NO_ERROR; - ALOGV("start(%d), calling pid %d session %d tid %d", - mName, IPCThreadState::self()->getCallingPid(), mSessionId, tid); - // check for use case 2 with missing callback - if (isFastTrack() && (mSharedBuffer == 0) && (tid == 0)) { - ALOGW("AUDIO_OUTPUT_FLAG_FAST denied"); - mFlags &= ~IAudioFlinger::TRACK_FAST; - // FIXME the track must be invalidated and moved to another thread or - // attached directly to the normal mixer now - } + sp thread = mThread.promote(); if (thread != 0) { Mutex::Autolock _l(thread->mLock); @@ -4467,14 +4473,13 @@ getNextBuffer_exit: return NOT_ENOUGH_DATA; } -status_t AudioFlinger::RecordThread::RecordTrack::start(pid_t tid, - AudioSystem::sync_event_t event, +status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event, int triggerSession) { sp thread = mThread.promote(); if (thread != 0) { RecordThread *recordThread = (RecordThread *)thread.get(); - return recordThread->start(this, tid, event, triggerSession); + return recordThread->start(this, event, triggerSession); } else { return BAD_VALUE; } @@ -4541,11 +4546,10 @@ AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack() clearBufferQueue(); } -status_t AudioFlinger::PlaybackThread::OutputTrack::start(pid_t tid, - AudioSystem::sync_event_t event, +status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event, int triggerSession) { - status_t status = Track::start(tid, event, triggerSession); + status_t status = Track::start(event, triggerSession); if (status != NO_ERROR) { return status; } @@ -4575,7 +4579,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr uint32_t waitTimeLeftMs = mSourceThread->waitTimeMs(); if (!mActive && frames != 0) { - start(0); + start(); sp thread = mThread.promote(); if (thread != 0) { MixerThread *mixerThread = (MixerThread *)thread.get(); @@ -4834,8 +4838,8 @@ sp AudioFlinger::TrackHandle::getCblk() const { return mTrack->getCblk(); } -status_t AudioFlinger::TrackHandle::start(pid_t tid) { - return mTrack->start(tid); +status_t AudioFlinger::TrackHandle::start() { + return mTrack->start(); } void AudioFlinger::TrackHandle::stop() { @@ -4988,9 +4992,9 @@ sp AudioFlinger::RecordHandle::getCblk() const { return mRecordTrack->getCblk(); } -status_t AudioFlinger::RecordHandle::start(pid_t tid, int event, int triggerSession) { +status_t AudioFlinger::RecordHandle::start(int event, int triggerSession) { ALOGV("RecordHandle::start()"); - return mRecordTrack->start(tid, (AudioSystem::sync_event_t)event, triggerSession); + return mRecordTrack->start((AudioSystem::sync_event_t)event, triggerSession); } void AudioFlinger::RecordHandle::stop() { @@ -5291,9 +5295,10 @@ Exit: } status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack, - pid_t tid, AudioSystem::sync_event_t event, + AudioSystem::sync_event_t event, int triggerSession) { + // FIXME use tid here ALOGV("RecordThread::start tid=%d, event %d, triggerSession %d", tid, event, triggerSession); sp strongMe = this; status_t status = NO_ERROR; diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index b1c5554..6b18945 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -91,6 +91,7 @@ public: IAudioFlinger::track_flags_t flags, const sp& sharedBuffer, audio_io_handle_t output, + pid_t tid, int *sessionId, status_t *status); @@ -376,8 +377,7 @@ private: int sessionId); virtual ~TrackBase(); - virtual status_t start(pid_t tid, - AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, + virtual status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, int triggerSession = 0) = 0; virtual void stop() = 0; sp getCblk() const { return mCblkMemory; } @@ -669,8 +669,7 @@ private: virtual ~Track(); void dump(char* buffer, size_t size); - virtual status_t start(pid_t tid, - AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, + virtual status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, int triggerSession = 0); virtual void stop(); void pause(); @@ -855,8 +854,7 @@ private: int frameCount); virtual ~OutputTrack(); - virtual status_t start(pid_t tid, - AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, + virtual status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, int triggerSession = 0); virtual void stop(); bool write(int16_t* data, uint32_t frames); @@ -933,6 +931,7 @@ public: const sp& sharedBuffer, int sessionId, IAudioFlinger::track_flags_t flags, + pid_t tid, status_t *status); AudioStreamOut* getOutput() const; @@ -1188,7 +1187,7 @@ private: TrackHandle(const sp& track); virtual ~TrackHandle(); virtual sp getCblk() const; - virtual status_t start(pid_t tid); + virtual status_t start(); virtual void stop(); virtual void flush(); virtual void mute(bool); @@ -1227,8 +1226,7 @@ private: int sessionId); virtual ~RecordTrack(); - virtual status_t start(pid_t tid, - AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, + virtual status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE, int triggerSession = 0); virtual void stop(); @@ -1276,7 +1274,7 @@ private: int sessionId, status_t *status); - status_t start(RecordTrack* recordTrack, pid_t tid, + status_t start(RecordTrack* recordTrack, AudioSystem::sync_event_t event, int triggerSession); void stop(RecordTrack* recordTrack); @@ -1335,7 +1333,7 @@ private: RecordHandle(const sp& recordTrack); virtual ~RecordHandle(); virtual sp getCblk() const; - virtual status_t start(pid_t tid, int event, int triggerSession); + virtual status_t start(int event, int triggerSession); virtual void stop(); virtual status_t onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); -- cgit v1.1