am 949c572a: am e7800946: Merge change I49f02be9 into eclair

Merge commit '949c572a16881aa40079a42bf7682637b23eb16a' into eclair-mr2-plus-aosp

* commit '949c572a16881aa40079a42bf7682637b23eb16a':
  Issue 2265163: Audio still reported routed through earpiece on sholes
This commit is contained in:
Eric Laurent
2009-11-21 00:26:09 -08:00
committed by Android Git Automerger
5 changed files with 216 additions and 144 deletions

View File

@@ -268,7 +268,7 @@ public:
* Returned value: * Returned value:
* handle on audio hardware input * handle on audio hardware input
*/ */
audio_io_handle_t getInput() { return mInput; } audio_io_handle_t getInput();
/* obtains a buffer of "frameCount" frames. The buffer must be /* obtains a buffer of "frameCount" frames. The buffer must be
* filled entirely. If the track is stopped, obtainBuffer() returns * filled entirely. If the track is stopped, obtainBuffer() returns
@@ -318,7 +318,8 @@ private:
int format, int format,
int channelCount, int channelCount,
int frameCount, int frameCount,
uint32_t flags); uint32_t flags,
audio_io_handle_t input);
sp<IAudioRecord> mAudioRecord; sp<IAudioRecord> mAudioRecord;
sp<IMemory> mCblkMemory; sp<IMemory> mCblkMemory;
@@ -345,8 +346,8 @@ private:
bool mMarkerReached; bool mMarkerReached;
uint32_t mNewPosition; uint32_t mNewPosition;
uint32_t mUpdatePeriod; uint32_t mUpdatePeriod;
audio_io_handle_t mInput;
uint32_t mFlags; uint32_t mFlags;
uint32_t mChannels;
}; };
}; // namespace android }; // namespace android

View File

@@ -674,32 +674,13 @@ void AudioFlinger::binderDied(const wp<IBinder>& who) {
} }
// audioConfigChanged_l() must be called with AudioFlinger::mLock held // audioConfigChanged_l() must be called with AudioFlinger::mLock held
void AudioFlinger::audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2) { void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2) {
int ioHandle = 0; size_t size = mNotificationClients.size();
for (size_t i = 0; i < size; i++) {
for (size_t i = 0; i < mPlaybackThreads.size(); i++) { sp<IBinder> binder = mNotificationClients.itemAt(i);
if (mPlaybackThreads.valueAt(i) == thread) { LOGV("audioConfigChanged_l() Notifying change to client %p", binder.get());
ioHandle = mPlaybackThreads.keyAt(i); sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
break; client->ioConfigChanged(event, ioHandle, param2);
}
}
if (ioHandle == 0) {
for (size_t i = 0; i < mRecordThreads.size(); i++) {
if (mRecordThreads.valueAt(i) == thread) {
ioHandle = mRecordThreads.keyAt(i);
break;
}
}
}
if (ioHandle != 0) {
size_t size = mNotificationClients.size();
for (size_t i = 0; i < size; i++) {
sp<IBinder> binder = mNotificationClients.itemAt(i);
LOGV("audioConfigChanged_l() Notifying change to client %p", binder.get());
sp<IAudioFlingerClient> client = interface_cast<IAudioFlingerClient> (binder);
client->ioConfigChanged(event, ioHandle, param2);
}
} }
} }
@@ -712,10 +693,10 @@ void AudioFlinger::removeClient_l(pid_t pid)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger) AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
: Thread(false), : Thread(false),
mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0), mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0),
mFormat(0), mFrameSize(1), mStandby(false) mFormat(0), mFrameSize(1), mStandby(false), mId(id), mExiting(false)
{ {
} }
@@ -734,6 +715,7 @@ void AudioFlinger::ThreadBase::exit()
LOGV("ThreadBase::exit"); LOGV("ThreadBase::exit");
{ {
AutoMutex lock(&mLock); AutoMutex lock(&mLock);
mExiting = true;
requestExit(); requestExit();
mWaitWorkCV.signal(); mWaitWorkCV.signal();
} }
@@ -870,8 +852,8 @@ status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
: ThreadBase(audioFlinger), : ThreadBase(audioFlinger, id),
mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output), mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false) mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
{ {
@@ -1106,15 +1088,6 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
{ {
status_t status = ALREADY_EXISTS; status_t status = ALREADY_EXISTS;
// here the track could be either new, or restarted
// in both cases "unstop" the track
if (track->isPaused()) {
track->mState = TrackBase::RESUMING;
LOGV("PAUSED => RESUMING (%d) on thread %p", track->name(), this);
} else {
track->mState = TrackBase::ACTIVE;
LOGV("? => ACTIVE (%d) on thread %p", track->name(), this);
}
// set retry count for buffer fill // set retry count for buffer fill
track->mRetryCount = kMaxTrackStartupRetries; track->mRetryCount = kMaxTrackStartupRetries;
if (mActiveTracks.indexOf(track) < 0) { if (mActiveTracks.indexOf(track) < 0) {
@@ -1173,7 +1146,7 @@ void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) {
break; break;
} }
Mutex::Autolock _l(mAudioFlinger->mLock); Mutex::Autolock _l(mAudioFlinger->mLock);
mAudioFlinger->audioConfigChanged_l(event, this, param2); mAudioFlinger->audioConfigChanged_l(event, mId, param2);
} }
void AudioFlinger::PlaybackThread::readOutputParameters() void AudioFlinger::PlaybackThread::readOutputParameters()
@@ -1194,8 +1167,8 @@ void AudioFlinger::PlaybackThread::readOutputParameters()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
: PlaybackThread(audioFlinger, output), : PlaybackThread(audioFlinger, output, id),
mAudioMixer(0) mAudioMixer(0)
{ {
mType = PlaybackThread::MIXER; mType = PlaybackThread::MIXER;
@@ -1303,7 +1276,6 @@ bool AudioFlinger::MixerThread::threadLoop()
} }
} else if (mBytesWritten != 0 || } else if (mBytesWritten != 0 ||
(mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) { (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
LOGV("NO DATA READY, %p", this);
memset (curBuf, 0, mixBufferSize); memset (curBuf, 0, mixBufferSize);
sleepTime = 0; sleepTime = 0;
LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start"); LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
@@ -1639,8 +1611,8 @@ uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
: PlaybackThread(audioFlinger, output), : PlaybackThread(audioFlinger, output, id),
mLeftVolume (1.0), mRightVolume(1.0) mLeftVolume (1.0), mRightVolume(1.0)
{ {
mType = PlaybackThread::DIRECT; mType = PlaybackThread::DIRECT;
@@ -1941,8 +1913,8 @@ uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread) AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
: MixerThread(audioFlinger, mainThread->getOutput()) : MixerThread(audioFlinger, mainThread->getOutput(), id)
{ {
mType = PlaybackThread::DUPLICATING; mType = PlaybackThread::DUPLICATING;
addOutputTrack(mainThread); addOutputTrack(mainThread);
@@ -2305,8 +2277,10 @@ AudioFlinger::PlaybackThread::Track::~Track()
LOGV("PlaybackThread::Track destructor"); LOGV("PlaybackThread::Track destructor");
sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote();
if (thread != 0) { if (thread != 0) {
Mutex::Autolock _l(thread->mLock); thread->mLock.lock();
mState = TERMINATED; mState = TERMINATED;
thread->mLock.unlock();
AudioSystem::releaseOutput(thread->id());
} }
} }
@@ -2324,6 +2298,9 @@ void AudioFlinger::PlaybackThread::Track::destroy()
{ // scope for mLock { // scope for mLock
sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote();
if (thread != 0) { if (thread != 0) {
if (!isOutputTrack() && (mState == ACTIVE || mState == RESUMING)) {
AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
}
Mutex::Autolock _l(thread->mLock); Mutex::Autolock _l(thread->mLock);
PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
playbackThread->destroyTrack_l(this); playbackThread->destroyTrack_l(this);
@@ -2405,14 +2382,37 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const {
status_t AudioFlinger::PlaybackThread::Track::start() status_t AudioFlinger::PlaybackThread::Track::start()
{ {
status_t status = NO_ERROR;
LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote();
if (thread != 0) { if (thread != 0) {
Mutex::Autolock _l(thread->mLock); Mutex::Autolock _l(thread->mLock);
PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); int state = mState;
playbackThread->addTrack_l(this); // here the track could be either new, or restarted
// in both cases "unstop" the track
if (mState == PAUSED) {
mState = TrackBase::RESUMING;
LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this);
} else {
mState = TrackBase::ACTIVE;
LOGV("? => ACTIVE (%d) on thread %p", mName, this);
}
if (!isOutputTrack() && state != ACTIVE && state != RESUMING) {
thread->mLock.unlock();
status = AudioSystem::startOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
thread->mLock.lock();
}
if (status == NO_ERROR) {
PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
playbackThread->addTrack_l(this);
} else {
mState = state;
}
} else {
status = BAD_VALUE;
} }
return NO_ERROR; return status;
} }
void AudioFlinger::PlaybackThread::Track::stop() void AudioFlinger::PlaybackThread::Track::stop()
@@ -2421,6 +2421,7 @@ void AudioFlinger::PlaybackThread::Track::stop()
sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote();
if (thread != 0) { if (thread != 0) {
Mutex::Autolock _l(thread->mLock); Mutex::Autolock _l(thread->mLock);
int state = mState;
if (mState > STOPPED) { if (mState > STOPPED) {
mState = STOPPED; mState = STOPPED;
// If the track is not active (PAUSED and buffers full), flush buffers // If the track is not active (PAUSED and buffers full), flush buffers
@@ -2430,6 +2431,11 @@ void AudioFlinger::PlaybackThread::Track::stop()
} }
LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread); LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread);
} }
if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) {
thread->mLock.unlock();
AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
thread->mLock.lock();
}
} }
} }
@@ -2442,6 +2448,11 @@ void AudioFlinger::PlaybackThread::Track::pause()
if (mState == ACTIVE || mState == RESUMING) { if (mState == ACTIVE || mState == RESUMING) {
mState = PAUSING; mState = PAUSING;
LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get()); LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get());
if (!isOutputTrack()) {
thread->mLock.unlock();
AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
thread->mLock.lock();
}
} }
} }
} }
@@ -2525,6 +2536,10 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack(
AudioFlinger::RecordThread::RecordTrack::~RecordTrack() AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
{ {
sp<ThreadBase> thread = mThread.promote();
if (thread != 0) {
AudioSystem::releaseInput(thread->id());
}
} }
status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer) status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
@@ -2572,8 +2587,9 @@ status_t AudioFlinger::RecordThread::RecordTrack::start()
if (thread != 0) { if (thread != 0) {
RecordThread *recordThread = (RecordThread *)thread.get(); RecordThread *recordThread = (RecordThread *)thread.get();
return recordThread->start(this); return recordThread->start(this);
} else {
return BAD_VALUE;
} }
return NO_INIT;
} }
void AudioFlinger::RecordThread::RecordTrack::stop() void AudioFlinger::RecordThread::RecordTrack::stop()
@@ -3010,8 +3026,8 @@ status_t AudioFlinger::RecordHandle::onTransact(
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels) : AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
ThreadBase(audioFlinger), ThreadBase(audioFlinger, id),
mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0) mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
{ {
mReqChannelCount = AudioSystem::popCount(channels); mReqChannelCount = AudioSystem::popCount(channels);
@@ -3039,6 +3055,7 @@ void AudioFlinger::RecordThread::onFirstRef()
run(buffer, PRIORITY_URGENT_AUDIO); run(buffer, PRIORITY_URGENT_AUDIO);
} }
bool AudioFlinger::RecordThread::threadLoop() bool AudioFlinger::RecordThread::threadLoop()
{ {
AudioBufferProvider::Buffer buffer; AudioBufferProvider::Buffer buffer;
@@ -3084,6 +3101,10 @@ bool AudioFlinger::RecordThread::threadLoop()
} }
if (mActiveTrack != 0) { if (mActiveTrack != 0) {
if (mActiveTrack->mState != TrackBase::ACTIVE) {
usleep(5000);
continue;
}
buffer.frameCount = mFrameCount; buffer.frameCount = mFrameCount;
if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) { if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
size_t framesOut = buffer.frameCount; size_t framesOut = buffer.frameCount;
@@ -3181,6 +3202,8 @@ bool AudioFlinger::RecordThread::threadLoop()
} }
mActiveTrack.clear(); mActiveTrack.clear();
mStartStopCond.broadcast();
LOGV("RecordThread %p exiting", this); LOGV("RecordThread %p exiting", this);
return false; return false;
} }
@@ -3188,37 +3211,71 @@ bool AudioFlinger::RecordThread::threadLoop()
status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack) status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
{ {
LOGV("RecordThread::start"); LOGV("RecordThread::start");
AutoMutex lock(&mLock); sp <ThreadBase> strongMe = this;
status_t status = NO_ERROR;
{
AutoMutex lock(&mLock);
if (mActiveTrack != 0) {
if (recordTrack != mActiveTrack.get()) {
status = -EBUSY;
} else if (mActiveTrack->mState == TrackBase::PAUSING) {
mActiveTrack->mState = TrackBase::RESUMING;
}
return status;
}
if (mActiveTrack != 0) { recordTrack->mState = TrackBase::IDLE;
if (recordTrack != mActiveTrack.get()) return -EBUSY; mActiveTrack = recordTrack;
mLock.unlock();
if (mActiveTrack->mState == TrackBase::PAUSING) mActiveTrack->mState = TrackBase::RESUMING; status_t status = AudioSystem::startInput(mId);
mLock.lock();
return NO_ERROR; if (status != NO_ERROR) {
} mActiveTrack.clear();
return status;
mActiveTrack = recordTrack; }
mActiveTrack->mState = TrackBase::RESUMING; mActiveTrack->mState = TrackBase::RESUMING;
// signal thread to start // signal thread to start
LOGV("Signal record thread"); LOGV("Signal record thread");
mWaitWorkCV.signal(); mWaitWorkCV.signal();
mStartStopCond.wait(mLock); // do not wait for mStartStopCond if exiting
if (mActiveTrack != 0) { if (mExiting) {
mActiveTrack.clear();
status = INVALID_OPERATION;
goto startError;
}
mStartStopCond.wait(mLock);
if (mActiveTrack == 0) {
LOGV("Record failed to start");
status = BAD_VALUE;
goto startError;
}
LOGV("Record started OK"); LOGV("Record started OK");
return NO_ERROR; return status;
} else {
LOGV("Record failed to start");
return BAD_VALUE;
} }
startError:
AudioSystem::stopInput(mId);
return status;
} }
void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) { void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
LOGV("RecordThread::stop"); LOGV("RecordThread::stop");
AutoMutex lock(&mLock); sp <ThreadBase> strongMe = this;
if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) { {
mActiveTrack->mState = TrackBase::PAUSING; AutoMutex lock(&mLock);
mStartStopCond.wait(mLock); if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
mActiveTrack->mState = TrackBase::PAUSING;
// do not wait for mStartStopCond if exiting
if (mExiting) {
return;
}
mStartStopCond.wait(mLock);
// if we have been restarted, recordTrack == mActiveTrack.get() here
if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
mLock.unlock();
AudioSystem::stopInput(mId);
mLock.lock();
}
}
} }
} }
@@ -3388,7 +3445,7 @@ void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) {
break; break;
} }
Mutex::Autolock _l(mAudioFlinger->mLock); Mutex::Autolock _l(mAudioFlinger->mLock);
mAudioFlinger->audioConfigChanged_l(event, this, param2); mAudioFlinger->audioConfigChanged_l(event, mId, param2);
} }
void AudioFlinger::RecordThread::readInputParameters() void AudioFlinger::RecordThread::readInputParameters()
@@ -3476,13 +3533,13 @@ int AudioFlinger::openOutput(uint32_t *pDevices,
if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) || if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
(format != AudioSystem::PCM_16_BIT) || (format != AudioSystem::PCM_16_BIT) ||
(channels != AudioSystem::CHANNEL_OUT_STEREO)) { (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
thread = new DirectOutputThread(this, output); thread = new DirectOutputThread(this, output, ++mNextThreadId);
LOGV("openOutput() created direct output: ID %d thread %p", (mNextThreadId + 1), thread); LOGV("openOutput() created direct output: ID %d thread %p", mNextThreadId, thread);
} else { } else {
thread = new MixerThread(this, output); thread = new MixerThread(this, output, ++mNextThreadId);
LOGV("openOutput() created mixer output: ID %d thread %p", (mNextThreadId + 1), thread); LOGV("openOutput() created mixer output: ID %d thread %p", mNextThreadId, thread);
} }
mPlaybackThreads.add(++mNextThreadId, thread); mPlaybackThreads.add(mNextThreadId, thread);
if (pSamplingRate) *pSamplingRate = samplingRate; if (pSamplingRate) *pSamplingRate = samplingRate;
if (pFormat) *pFormat = format; if (pFormat) *pFormat = format;
@@ -3505,9 +3562,9 @@ int AudioFlinger::openDuplicateOutput(int output1, int output2)
} }
DuplicatingThread *thread = new DuplicatingThread(this, thread1); DuplicatingThread *thread = new DuplicatingThread(this, thread1, ++mNextThreadId);
thread->addOutputTrack(thread2); thread->addOutputTrack(thread2);
mPlaybackThreads.add(++mNextThreadId, thread); mPlaybackThreads.add(mNextThreadId, thread);
return mNextThreadId; return mNextThreadId;
} }
@@ -3534,7 +3591,7 @@ status_t AudioFlinger::closeOutput(int output)
} }
} }
void *param2 = 0; void *param2 = 0;
audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, thread, param2); audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
mPlaybackThreads.removeItem(output); mPlaybackThreads.removeItem(output);
} }
thread->exit(); thread->exit();
@@ -3628,8 +3685,8 @@ int AudioFlinger::openInput(uint32_t *pDevices,
if (input != 0) { if (input != 0) {
// Start record thread // Start record thread
thread = new RecordThread(this, input, reqSamplingRate, reqChannels); thread = new RecordThread(this, input, reqSamplingRate, reqChannels, ++mNextThreadId);
mRecordThreads.add(++mNextThreadId, thread); mRecordThreads.add(mNextThreadId, thread);
LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread); LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread);
if (pSamplingRate) *pSamplingRate = reqSamplingRate; if (pSamplingRate) *pSamplingRate = reqSamplingRate;
if (pFormat) *pFormat = format; if (pFormat) *pFormat = format;
@@ -3655,7 +3712,7 @@ status_t AudioFlinger::closeInput(int input)
LOGV("closeInput() %d", input); LOGV("closeInput() %d", input);
void *param2 = 0; void *param2 = 0;
audioConfigChanged_l(AudioSystem::INPUT_CLOSED, thread, param2); audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
mRecordThreads.removeItem(input); mRecordThreads.removeItem(input);
} }
thread->exit(); thread->exit();

View File

@@ -213,7 +213,7 @@ private:
class ThreadBase : public Thread { class ThreadBase : public Thread {
public: public:
ThreadBase (const sp<AudioFlinger>& audioFlinger); ThreadBase (const sp<AudioFlinger>& audioFlinger, int id);
virtual ~ThreadBase(); virtual ~ThreadBase();
status_t dumpBase(int fd, const Vector<String16>& args); status_t dumpBase(int fd, const Vector<String16>& args);
@@ -323,6 +323,7 @@ private:
void sendConfigEvent(int event, int param = 0); void sendConfigEvent(int event, int param = 0);
void sendConfigEvent_l(int event, int param = 0); void sendConfigEvent_l(int event, int param = 0);
void processConfigEvents(); void processConfigEvents();
int id() const { return mId;}
mutable Mutex mLock; mutable Mutex mLock;
@@ -349,6 +350,8 @@ private:
status_t mParamStatus; status_t mParamStatus;
Vector<ConfigEvent *> mConfigEvents; Vector<ConfigEvent *> mConfigEvents;
bool mStandby; bool mStandby;
int mId;
bool mExiting;
}; };
// --- PlaybackThread --- // --- PlaybackThread ---
@@ -421,6 +424,10 @@ private:
void setPaused() { mState = PAUSED; } void setPaused() { mState = PAUSED; }
void reset(); void reset();
bool isOutputTrack() const {
return (mStreamType == AudioSystem::NUM_STREAM_TYPES);
}
// we don't really need a lock for these // we don't really need a lock for these
float mVolume[2]; float mVolume[2];
volatile bool mMute; volatile bool mMute;
@@ -473,7 +480,7 @@ private:
}; // end of OutputTrack }; // end of OutputTrack
PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
virtual ~PlaybackThread(); virtual ~PlaybackThread();
virtual status_t dump(int fd, const Vector<String16>& args); virtual status_t dump(int fd, const Vector<String16>& args);
@@ -573,7 +580,7 @@ private:
class MixerThread : public PlaybackThread { class MixerThread : public PlaybackThread {
public: public:
MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
virtual ~MixerThread(); virtual ~MixerThread();
// Thread virtuals // Thread virtuals
@@ -600,7 +607,7 @@ private:
class DirectOutputThread : public PlaybackThread { class DirectOutputThread : public PlaybackThread {
public: public:
DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
~DirectOutputThread(); ~DirectOutputThread();
// Thread virtuals // Thread virtuals
@@ -621,7 +628,7 @@ private:
class DuplicatingThread : public MixerThread { class DuplicatingThread : public MixerThread {
public: public:
DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread); DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread, int id);
~DuplicatingThread(); ~DuplicatingThread();
// Thread virtuals // Thread virtuals
@@ -637,7 +644,7 @@ private:
MixerThread *checkMixerThread_l(int output) const; MixerThread *checkMixerThread_l(int output) const;
RecordThread *checkRecordThread_l(int input) const; RecordThread *checkRecordThread_l(int input) const;
float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; } float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; }
void audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2); void audioConfigChanged_l(int event, int ioHandle, void *param2);
friend class AudioBuffer; friend class AudioBuffer;
@@ -705,7 +712,8 @@ private:
RecordThread(const sp<AudioFlinger>& audioFlinger, RecordThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamIn *input, AudioStreamIn *input,
uint32_t sampleRate, uint32_t sampleRate,
uint32_t channels); uint32_t channels,
int id);
~RecordThread(); ~RecordThread();
virtual bool threadLoop(); virtual bool threadLoop();

View File

@@ -46,7 +46,7 @@ namespace android {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
AudioRecord::AudioRecord() AudioRecord::AudioRecord()
: mStatus(NO_INIT), mInput(0) : mStatus(NO_INIT)
{ {
} }
@@ -60,7 +60,7 @@ AudioRecord::AudioRecord(
callback_t cbf, callback_t cbf,
void* user, void* user,
int notificationFrames) int notificationFrames)
: mStatus(NO_INIT), mInput(0) : mStatus(NO_INIT)
{ {
mStatus = set(inputSource, sampleRate, format, channels, mStatus = set(inputSource, sampleRate, format, channels,
frameCount, flags, cbf, user, notificationFrames); frameCount, flags, cbf, user, notificationFrames);
@@ -79,7 +79,6 @@ AudioRecord::~AudioRecord()
} }
mAudioRecord.clear(); mAudioRecord.clear();
IPCThreadState::self()->flushCommands(); IPCThreadState::self()->flushCommands();
AudioSystem::releaseInput(mInput);
} }
} }
@@ -123,9 +122,9 @@ status_t AudioRecord::set(
} }
int channelCount = AudioSystem::popCount(channels); int channelCount = AudioSystem::popCount(channels);
mInput = AudioSystem::getInput(inputSource, audio_io_handle_t input = AudioSystem::getInput(inputSource,
sampleRate, format, channels, (AudioSystem::audio_in_acoustics)flags); sampleRate, format, channels, (AudioSystem::audio_in_acoustics)flags);
if (mInput == 0) { if (input == 0) {
LOGE("Could not get audio output for stream type %d", inputSource); LOGE("Could not get audio output for stream type %d", inputSource);
return BAD_VALUE; return BAD_VALUE;
} }
@@ -168,7 +167,7 @@ status_t AudioRecord::set(
// create the IAudioRecord // create the IAudioRecord
status_t status = openRecord(sampleRate, format, channelCount, status_t status = openRecord(sampleRate, format, channelCount,
frameCount, flags); frameCount, flags, input);
if (status != NO_ERROR) { if (status != NO_ERROR) {
return status; return status;
@@ -187,6 +186,7 @@ status_t AudioRecord::set(
// Update buffer size in case it has been limited by AudioFlinger during track creation // Update buffer size in case it has been limited by AudioFlinger during track creation
mFrameCount = mCblk->frameCount; mFrameCount = mCblk->frameCount;
mChannelCount = (uint8_t)channelCount; mChannelCount = (uint8_t)channelCount;
mChannels = channels;
mActive = 0; mActive = 0;
mCbf = cbf; mCbf = cbf;
mNotificationFrames = notificationFrames; mNotificationFrames = notificationFrames;
@@ -265,29 +265,28 @@ status_t AudioRecord::start()
} }
if (android_atomic_or(1, &mActive) == 0) { if (android_atomic_or(1, &mActive) == 0) {
ret = AudioSystem::startInput(mInput); ret = mAudioRecord->start();
if (ret == NO_ERROR) { if (ret == DEAD_OBJECT) {
ret = mAudioRecord->start(); LOGV("start() dead IAudioRecord: creating a new one");
if (ret == DEAD_OBJECT) { ret = openRecord(mCblk->sampleRate, mFormat, mChannelCount,
LOGV("start() dead IAudioRecord: creating a new one"); mFrameCount, mFlags, getInput());
ret = openRecord(mCblk->sampleRate, mFormat, mChannelCount,
mFrameCount, mFlags);
}
if (ret == NO_ERROR) { if (ret == NO_ERROR) {
mNewPosition = mCblk->user + mUpdatePeriod; ret = mAudioRecord->start();
mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
if (t != 0) {
t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
} else {
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
}
} else {
LOGV("start() failed");
AudioSystem::stopInput(mInput);
android_atomic_and(~1, &mActive);
} }
} }
if (ret == NO_ERROR) {
mNewPosition = mCblk->user + mUpdatePeriod;
mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
if (t != 0) {
t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
} else {
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
}
} else {
LOGV("start() failed");
android_atomic_and(~1, &mActive);
}
} }
if (t != 0) { if (t != 0) {
@@ -318,7 +317,6 @@ status_t AudioRecord::stop()
} else { } else {
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL); setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
} }
AudioSystem::stopInput(mInput);
} }
if (t != 0) { if (t != 0) {
@@ -395,7 +393,8 @@ status_t AudioRecord::openRecord(
int format, int format,
int channelCount, int channelCount,
int frameCount, int frameCount,
uint32_t flags) uint32_t flags,
audio_io_handle_t input)
{ {
status_t status; status_t status;
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger(); const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
@@ -403,7 +402,7 @@ status_t AudioRecord::openRecord(
return NO_INIT; return NO_INIT;
} }
sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), mInput, sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
sampleRate, format, sampleRate, format,
channelCount, channelCount,
frameCount, frameCount,
@@ -425,7 +424,8 @@ status_t AudioRecord::openRecord(
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer()); mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t); mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
mCblk->out = 0; mCblk->out = 0;
mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
return NO_ERROR; return NO_ERROR;
} }
@@ -466,10 +466,10 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
if (result == DEAD_OBJECT) { if (result == DEAD_OBJECT) {
LOGW("obtainBuffer() dead IAudioRecord: creating a new one"); LOGW("obtainBuffer() dead IAudioRecord: creating a new one");
result = openRecord(cblk->sampleRate, mFormat, mChannelCount, result = openRecord(cblk->sampleRate, mFormat, mChannelCount,
mFrameCount, mFlags); mFrameCount, mFlags, getInput());
if (result == NO_ERROR) { if (result == NO_ERROR) {
cblk = mCblk; cblk = mCblk;
cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; mAudioRecord->start();
} }
} }
cblk->lock.lock(); cblk->lock.lock();
@@ -516,6 +516,14 @@ void AudioRecord::releaseBuffer(Buffer* audioBuffer)
cblk->stepUser(audioBuffer->frameCount); cblk->stepUser(audioBuffer->frameCount);
} }
audio_io_handle_t AudioRecord::getInput()
{
return AudioSystem::getInput(mInputSource,
mCblk->sampleRate,
mFormat, mChannels,
(AudioSystem::audio_in_acoustics)mFlags);
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
ssize_t AudioRecord::read(void* buffer, size_t userSize) ssize_t AudioRecord::read(void* buffer, size_t userSize)

View File

@@ -97,7 +97,6 @@ AudioTrack::~AudioTrack()
} }
mAudioTrack.clear(); mAudioTrack.clear();
IPCThreadState::self()->flushCommands(); IPCThreadState::self()->flushCommands();
AudioSystem::releaseOutput(getOutput());
} }
} }
@@ -318,8 +317,6 @@ void AudioTrack::start()
} }
if (android_atomic_or(1, &mActive) == 0) { if (android_atomic_or(1, &mActive) == 0) {
audio_io_handle_t output = getOutput();
AudioSystem::startOutput(output, (AudioSystem::stream_type)mStreamType);
mNewPosition = mCblk->server + mUpdatePeriod; mNewPosition = mCblk->server + mUpdatePeriod;
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
mCblk->waitTimeMs = 0; mCblk->waitTimeMs = 0;
@@ -333,10 +330,13 @@ void AudioTrack::start()
if (status == DEAD_OBJECT) { if (status == DEAD_OBJECT) {
LOGV("start() dead IAudioTrack: creating a new one"); LOGV("start() dead IAudioTrack: creating a new one");
status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount, status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount,
mFrameCount, mFlags, mSharedBuffer, output); mFrameCount, mFlags, mSharedBuffer, getOutput());
mNewPosition = mCblk->server + mUpdatePeriod; if (status == NO_ERROR) {
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; status = mAudioTrack->start();
mCblk->waitTimeMs = 0; if (status == NO_ERROR) {
mNewPosition = mCblk->server + mUpdatePeriod;
}
}
} }
if (status != NO_ERROR) { if (status != NO_ERROR) {
LOGV("start() failed"); LOGV("start() failed");
@@ -346,7 +346,6 @@ void AudioTrack::start()
} else { } else {
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL); setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
} }
AudioSystem::stopOutput(output, (AudioSystem::stream_type)mStreamType);
} }
} }
@@ -383,7 +382,6 @@ void AudioTrack::stop()
} else { } else {
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL); setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
} }
AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
} }
if (t != 0) { if (t != 0) {
@@ -418,9 +416,7 @@ void AudioTrack::pause()
{ {
LOGV("pause"); LOGV("pause");
if (android_atomic_and(~1, &mActive) == 1) { if (android_atomic_and(~1, &mActive) == 1) {
mActive = 0;
mAudioTrack->pause(); mAudioTrack->pause();
AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
} }
} }
@@ -658,7 +654,8 @@ status_t AudioTrack::createTrack(
} }
mCblk->volumeLR = (int32_t(int16_t(mVolume[LEFT] * 0x1000)) << 16) | int16_t(mVolume[RIGHT] * 0x1000); mCblk->volumeLR = (int32_t(int16_t(mVolume[LEFT] * 0x1000)) << 16) | int16_t(mVolume[RIGHT] * 0x1000);
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
mCblk->waitTimeMs = 0;
return NO_ERROR; return NO_ERROR;
} }
@@ -709,6 +706,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
if (result == NO_ERROR) { if (result == NO_ERROR) {
cblk = mCblk; cblk = mCblk;
cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
mAudioTrack->start();
} }
} }
cblk->lock.lock(); cblk->lock.lock();