Merge change I49f02be9 into eclair

* changes:
  Issue 2265163: Audio still reported routed through earpiece on sholes
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 008468c..622c596 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -268,7 +268,7 @@
      * Returned value:
      *  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
      * filled entirely. If the track is stopped, obtainBuffer() returns
@@ -318,7 +318,8 @@
                                 int format,
                                 int channelCount,
                                 int frameCount,
-                                uint32_t flags);
+                                uint32_t flags,
+                                audio_io_handle_t input);
 
     sp<IAudioRecord>        mAudioRecord;
     sp<IMemory>             mCblkMemory;
@@ -345,8 +346,8 @@
     bool                    mMarkerReached;
     uint32_t                mNewPosition;
     uint32_t                mUpdatePeriod;
-    audio_io_handle_t       mInput;
     uint32_t                mFlags;
+    uint32_t                mChannels;
 };
 
 }; // namespace android
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index d918998..daec6e8 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -674,32 +674,13 @@
 }
 
 // audioConfigChanged_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2) {
-    int ioHandle = 0;
-
-    for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        if (mPlaybackThreads.valueAt(i) == thread) {
-            ioHandle = mPlaybackThreads.keyAt(i);
-            break;
-        }
-    }
-    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);
-        }
+void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2) {
+    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 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger)
+AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id)
     :   Thread(false),
         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 @@
     LOGV("ThreadBase::exit");
     {
         AutoMutex lock(&mLock);
+        mExiting = true;
         requestExit();
         mWaitWorkCV.signal();
     }
@@ -870,8 +852,8 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
-    :   ThreadBase(audioFlinger),
+AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
+    :   ThreadBase(audioFlinger, id),
         mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output),
         mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false)
 {
@@ -1106,15 +1088,6 @@
 {
     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
     track->mRetryCount = kMaxTrackStartupRetries;
     if (mActiveTracks.indexOf(track) < 0) {
@@ -1173,7 +1146,7 @@
         break;
     }
     Mutex::Autolock _l(mAudioFlinger->mLock);
-    mAudioFlinger->audioConfigChanged_l(event, this, param2);
+    mAudioFlinger->audioConfigChanged_l(event, mId, param2);
 }
 
 void AudioFlinger::PlaybackThread::readOutputParameters()
@@ -1194,8 +1167,8 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
-    :   PlaybackThread(audioFlinger, output),
+AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
+    :   PlaybackThread(audioFlinger, output, id),
         mAudioMixer(0)
 {
     mType = PlaybackThread::MIXER;
@@ -1303,7 +1276,6 @@
                 }
             } else if (mBytesWritten != 0 ||
                        (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
-                LOGV("NO DATA READY, %p", this);
                 memset (curBuf, 0, mixBufferSize);
                 sleepTime = 0;
                 LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
@@ -1639,8 +1611,8 @@
 }
 
 // ----------------------------------------------------------------------------
-AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output)
-    :   PlaybackThread(audioFlinger, output),
+AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id)
+    :   PlaybackThread(audioFlinger, output, id),
     mLeftVolume (1.0), mRightVolume(1.0)
 {
     mType = PlaybackThread::DIRECT;
@@ -1941,8 +1913,8 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread)
-    :   MixerThread(audioFlinger, mainThread->getOutput())
+AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id)
+    :   MixerThread(audioFlinger, mainThread->getOutput(), id)
 {
     mType = PlaybackThread::DUPLICATING;
     addOutputTrack(mainThread);
@@ -2305,8 +2277,10 @@
     LOGV("PlaybackThread::Track destructor");
     sp<ThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        Mutex::Autolock _l(thread->mLock);
+        thread->mLock.lock();
         mState = TERMINATED;
+        thread->mLock.unlock();
+        AudioSystem::releaseOutput(thread->id());
     }
 }
 
@@ -2324,6 +2298,9 @@
     { // scope for mLock
         sp<ThreadBase> thread = mThread.promote();
         if (thread != 0) {
+            if (!isOutputTrack() && (mState == ACTIVE || mState == RESUMING)) {
+                AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType);
+            }
             Mutex::Autolock _l(thread->mLock);
             PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
             playbackThread->destroyTrack_l(this);
@@ -2405,14 +2382,37 @@
 
 status_t AudioFlinger::PlaybackThread::Track::start()
 {
+    status_t status = NO_ERROR;
     LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
     sp<ThreadBase> thread = mThread.promote();
     if (thread != 0) {
         Mutex::Autolock _l(thread->mLock);
-        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
-        playbackThread->addTrack_l(this);
+        int state = mState;
+        // 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()
@@ -2421,6 +2421,7 @@
     sp<ThreadBase> thread = mThread.promote();
     if (thread != 0) {
         Mutex::Autolock _l(thread->mLock);
+        int state = mState;
         if (mState > STOPPED) {
             mState = STOPPED;
             // If the track is not active (PAUSED and buffers full), flush buffers
@@ -2430,6 +2431,11 @@
             }
             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 @@
         if (mState == ACTIVE || mState == RESUMING) {
             mState = PAUSING;
             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()
 {
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0) {
+        AudioSystem::releaseInput(thread->id());
+    }
 }
 
 status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
@@ -2572,8 +2587,9 @@
     if (thread != 0) {
         RecordThread *recordThread = (RecordThread *)thread.get();
         return recordThread->start(this);
+    } else {
+        return BAD_VALUE;
     }
-    return NO_INIT;
 }
 
 void AudioFlinger::RecordThread::RecordTrack::stop()
@@ -3010,8 +3026,8 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels) :
-    ThreadBase(audioFlinger),
+AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) :
+    ThreadBase(audioFlinger, id),
     mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0)
 {
     mReqChannelCount = AudioSystem::popCount(channels);
@@ -3039,6 +3055,7 @@
 
     run(buffer, PRIORITY_URGENT_AUDIO);
 }
+
 bool AudioFlinger::RecordThread::threadLoop()
 {
     AudioBufferProvider::Buffer buffer;
@@ -3084,6 +3101,10 @@
         }
 
         if (mActiveTrack != 0) {
+            if (mActiveTrack->mState != TrackBase::ACTIVE) {
+                usleep(5000);
+                continue;
+            }
             buffer.frameCount = mFrameCount;
             if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) {
                 size_t framesOut = buffer.frameCount;
@@ -3181,6 +3202,8 @@
     }
     mActiveTrack.clear();
 
+    mStartStopCond.broadcast();
+
     LOGV("RecordThread %p exiting", this);
     return false;
 }
@@ -3188,37 +3211,71 @@
 status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack)
 {
     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) {
-        if (recordTrack != mActiveTrack.get()) return -EBUSY;
-
-        if (mActiveTrack->mState == TrackBase::PAUSING) mActiveTrack->mState = TrackBase::RESUMING;
-
-        return NO_ERROR;
-    }
-
-    mActiveTrack = recordTrack;
-    mActiveTrack->mState = TrackBase::RESUMING;
-    // signal thread to start
-    LOGV("Signal record thread");
-    mWaitWorkCV.signal();
-    mStartStopCond.wait(mLock);
-    if (mActiveTrack != 0) {
+        recordTrack->mState = TrackBase::IDLE;
+        mActiveTrack = recordTrack;
+        mLock.unlock();
+        status_t status = AudioSystem::startInput(mId);
+        mLock.lock();
+        if (status != NO_ERROR) {
+            mActiveTrack.clear();
+            return status;
+        }
+        mActiveTrack->mState = TrackBase::RESUMING;
+        // signal thread to start
+        LOGV("Signal record thread");
+        mWaitWorkCV.signal();
+        // do not wait for mStartStopCond if exiting
+        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");
-        return NO_ERROR;
-    } else {
-        LOGV("Record failed to start");
-        return BAD_VALUE;
+        return status;
     }
+startError:
+    AudioSystem::stopInput(mId);
+    return status;
 }
 
 void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
     LOGV("RecordThread::stop");
-    AutoMutex lock(&mLock);
-    if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
-        mActiveTrack->mState = TrackBase::PAUSING;
-        mStartStopCond.wait(mLock);
+    sp <ThreadBase> strongMe = this;
+    {
+        AutoMutex lock(&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 @@
         break;
     }
     Mutex::Autolock _l(mAudioFlinger->mLock);
-    mAudioFlinger->audioConfigChanged_l(event, this, param2);
+    mAudioFlinger->audioConfigChanged_l(event, mId, param2);
 }
 
 void AudioFlinger::RecordThread::readInputParameters()
@@ -3476,13 +3533,13 @@
         if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
             (format != AudioSystem::PCM_16_BIT) ||
             (channels != AudioSystem::CHANNEL_OUT_STEREO)) {
-            thread = new DirectOutputThread(this, output);
-            LOGV("openOutput() created direct output: ID %d thread %p", (mNextThreadId + 1), thread);
+            thread = new DirectOutputThread(this, output, ++mNextThreadId);
+            LOGV("openOutput() created direct output: ID %d thread %p", mNextThreadId, thread);
         } else {
-            thread = new MixerThread(this, output);
-            LOGV("openOutput() created mixer output: ID %d thread %p", (mNextThreadId + 1), thread);
+            thread = new MixerThread(this, output, ++mNextThreadId);
+            LOGV("openOutput() created mixer output: ID %d thread %p", mNextThreadId, thread);
         }
-        mPlaybackThreads.add(++mNextThreadId, thread);
+        mPlaybackThreads.add(mNextThreadId, thread);
 
         if (pSamplingRate) *pSamplingRate = samplingRate;
         if (pFormat) *pFormat = format;
@@ -3505,9 +3562,9 @@
     }
 
 
-    DuplicatingThread *thread = new DuplicatingThread(this, thread1);
+    DuplicatingThread *thread = new DuplicatingThread(this, thread1, ++mNextThreadId);
     thread->addOutputTrack(thread2);
-    mPlaybackThreads.add(++mNextThreadId, thread);
+    mPlaybackThreads.add(mNextThreadId, thread);
     return mNextThreadId;
 }
 
@@ -3534,7 +3591,7 @@
             }
         }
         void *param2 = 0;
-        audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, thread, param2);
+        audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2);
         mPlaybackThreads.removeItem(output);
     }
     thread->exit();
@@ -3628,8 +3685,8 @@
 
     if (input != 0) {
          // Start record thread
-        thread = new RecordThread(this, input, reqSamplingRate, reqChannels);
-        mRecordThreads.add(++mNextThreadId, thread);
+        thread = new RecordThread(this, input, reqSamplingRate, reqChannels, ++mNextThreadId);
+        mRecordThreads.add(mNextThreadId, thread);
         LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread);
         if (pSamplingRate) *pSamplingRate = reqSamplingRate;
         if (pFormat) *pFormat = format;
@@ -3655,7 +3712,7 @@
 
         LOGV("closeInput() %d", input);
         void *param2 = 0;
-        audioConfigChanged_l(AudioSystem::INPUT_CLOSED, thread, param2);
+        audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2);
         mRecordThreads.removeItem(input);
     }
     thread->exit();
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 594d878..5a17294 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -213,7 +213,7 @@
 
     class ThreadBase : public Thread {
     public:
-        ThreadBase (const sp<AudioFlinger>& audioFlinger);
+        ThreadBase (const sp<AudioFlinger>& audioFlinger, int id);
         virtual             ~ThreadBase();
 
         status_t dumpBase(int fd, const Vector<String16>& args);
@@ -323,6 +323,7 @@
                     void        sendConfigEvent(int event, int param = 0);
                     void        sendConfigEvent_l(int event, int param = 0);
                     void        processConfigEvents();
+                    int         id() const { return mId;}
 
         mutable     Mutex                   mLock;
 
@@ -349,6 +350,8 @@
                     status_t                mParamStatus;
                     Vector<ConfigEvent *>   mConfigEvents;
                     bool                    mStandby;
+                    int                     mId;
+                    bool                    mExiting;
     };
 
     // --- PlaybackThread ---
@@ -421,6 +424,10 @@
             void setPaused() { mState = PAUSED; }
             void reset();
 
+            bool isOutputTrack() const {
+                return (mStreamType == AudioSystem::NUM_STREAM_TYPES);
+            }
+
             // we don't really need a lock for these
             float               mVolume[2];
             volatile bool       mMute;
@@ -473,7 +480,7 @@
 
         };  // end of OutputTrack
 
-        PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output);
+        PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
         virtual             ~PlaybackThread();
 
         virtual     status_t    dump(int fd, const Vector<String16>& args);
@@ -573,7 +580,7 @@
 
     class MixerThread : public PlaybackThread {
     public:
-        MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output);
+        MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
         virtual             ~MixerThread();
 
         // Thread virtuals
@@ -600,7 +607,7 @@
     class DirectOutputThread : public PlaybackThread {
     public:
 
-        DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output);
+        DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id);
         ~DirectOutputThread();
 
         // Thread virtuals
@@ -621,7 +628,7 @@
 
     class DuplicatingThread : public MixerThread {
     public:
-        DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread);
+        DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread, int id);
         ~DuplicatingThread();
 
         // Thread virtuals
@@ -637,7 +644,7 @@
               MixerThread *checkMixerThread_l(int output) const;
               RecordThread *checkRecordThread_l(int input) const;
               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;
 
@@ -705,7 +712,8 @@
                 RecordThread(const sp<AudioFlinger>& audioFlinger,
                         AudioStreamIn *input,
                         uint32_t sampleRate,
-                        uint32_t channels);
+                        uint32_t channels,
+                        int id);
                 ~RecordThread();
 
         virtual bool        threadLoop();
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index e63c0d2..c3828f0 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -46,7 +46,7 @@
 // ---------------------------------------------------------------------------
 
 AudioRecord::AudioRecord()
-    : mStatus(NO_INIT), mInput(0)
+    : mStatus(NO_INIT)
 {
 }
 
@@ -60,7 +60,7 @@
         callback_t cbf,
         void* user,
         int notificationFrames)
-    : mStatus(NO_INIT), mInput(0)
+    : mStatus(NO_INIT)
 {
     mStatus = set(inputSource, sampleRate, format, channels,
             frameCount, flags, cbf, user, notificationFrames);
@@ -79,7 +79,6 @@
         }
         mAudioRecord.clear();
         IPCThreadState::self()->flushCommands();
-        AudioSystem::releaseInput(mInput);
     }
 }
 
@@ -123,9 +122,9 @@
     }
     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);
-    if (mInput == 0) {
+    if (input == 0) {
         LOGE("Could not get audio output for stream type %d", inputSource);
         return BAD_VALUE;
     }
@@ -168,7 +167,7 @@
 
     // create the IAudioRecord
     status_t status = openRecord(sampleRate, format, channelCount,
-                                 frameCount, flags);
+                                 frameCount, flags, input);
 
     if (status != NO_ERROR) {
         return status;
@@ -187,6 +186,7 @@
     // Update buffer size in case it has been limited by AudioFlinger during track creation
     mFrameCount = mCblk->frameCount;
     mChannelCount = (uint8_t)channelCount;
+    mChannels = channels;
     mActive = 0;
     mCbf = cbf;
     mNotificationFrames = notificationFrames;
@@ -265,29 +265,28 @@
      }
 
     if (android_atomic_or(1, &mActive) == 0) {
-        ret = AudioSystem::startInput(mInput);
-        if (ret == NO_ERROR) {
-            ret = mAudioRecord->start();
-            if (ret == DEAD_OBJECT) {
-                LOGV("start() dead IAudioRecord: creating a new one");
-                ret = openRecord(mCblk->sampleRate, mFormat, mChannelCount,
-                        mFrameCount, mFlags);
-            }
+        ret = mAudioRecord->start();
+        if (ret == DEAD_OBJECT) {
+            LOGV("start() dead IAudioRecord: creating a new one");
+            ret = openRecord(mCblk->sampleRate, mFormat, mChannelCount,
+                    mFrameCount, mFlags, getInput());
             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");
-                AudioSystem::stopInput(mInput);
-                android_atomic_and(~1, &mActive);
+                ret = mAudioRecord->start();
             }
         }
+        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) {
@@ -318,7 +317,6 @@
         } else {
             setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
         }
-        AudioSystem::stopInput(mInput);
     }
 
     if (t != 0) {
@@ -395,7 +393,8 @@
         int format,
         int channelCount,
         int frameCount,
-        uint32_t flags)
+        uint32_t flags,
+        audio_io_handle_t input)
 {
     status_t status;
     const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
@@ -403,7 +402,7 @@
         return NO_INIT;
     }
 
-    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), mInput,
+    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), input,
                                                        sampleRate, format,
                                                        channelCount,
                                                        frameCount,
@@ -425,7 +424,8 @@
     mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
     mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
     mCblk->out = 0;
-
+    mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+    mCblk->waitTimeMs = 0;
     return NO_ERROR;
 }
 
@@ -466,10 +466,10 @@
                     if (result == DEAD_OBJECT) {
                         LOGW("obtainBuffer() dead IAudioRecord: creating a new one");
                         result = openRecord(cblk->sampleRate, mFormat, mChannelCount,
-                                            mFrameCount, mFlags);
+                                            mFrameCount, mFlags, getInput());
                         if (result == NO_ERROR) {
                             cblk = mCblk;
-                            cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+                            mAudioRecord->start();
                         }
                     }
                     cblk->lock.lock();
@@ -516,6 +516,14 @@
     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)
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index cedd79d..ad0f42e 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -97,7 +97,6 @@
         }
         mAudioTrack.clear();
         IPCThreadState::self()->flushCommands();
-        AudioSystem::releaseOutput(getOutput());
     }
 }
 
@@ -318,8 +317,6 @@
      }
 
     if (android_atomic_or(1, &mActive) == 0) {
-        audio_io_handle_t output = getOutput();
-        AudioSystem::startOutput(output, (AudioSystem::stream_type)mStreamType);
         mNewPosition = mCblk->server + mUpdatePeriod;
         mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
         mCblk->waitTimeMs = 0;
@@ -333,10 +330,13 @@
         if (status == DEAD_OBJECT) {
             LOGV("start() dead IAudioTrack: creating a new one");
             status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount,
-                                 mFrameCount, mFlags, mSharedBuffer, output);
-            mNewPosition = mCblk->server + mUpdatePeriod;
-            mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
-            mCblk->waitTimeMs = 0;
+                                 mFrameCount, mFlags, mSharedBuffer, getOutput());
+            if (status == NO_ERROR) {
+                status = mAudioTrack->start();
+                if (status == NO_ERROR) {
+                    mNewPosition = mCblk->server + mUpdatePeriod;
+                }
+            }
         }
         if (status != NO_ERROR) {
             LOGV("start() failed");
@@ -346,7 +346,6 @@
             } else {
                 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
             }
-            AudioSystem::stopOutput(output, (AudioSystem::stream_type)mStreamType);
         }
     }
 
@@ -383,7 +382,6 @@
         } else {
             setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
         }
-        AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
     }
 
     if (t != 0) {
@@ -418,9 +416,7 @@
 {
     LOGV("pause");
     if (android_atomic_and(~1, &mActive) == 1) {
-        mActive = 0;
         mAudioTrack->pause();
-        AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
     }
 }
 
@@ -658,7 +654,8 @@
     }
 
     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;
 }
 
@@ -709,6 +706,7 @@
                             if (result == NO_ERROR) {
                                 cblk = mCblk;
                                 cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+                                mAudioTrack->start();
                             }
                         }
                         cblk->lock.lock();