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:
@@ -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
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user