Fix issue 1795088       Improve audio routing code

Initial commit for review.
Integrated comments after patch set 1 review.
Fixed lockup in AudioFlinger::ThreadBase::exit()
Fixed lockup when playing tone with AudioPlocyService startTone()
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 7b9eda7..b147d25 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -54,7 +54,7 @@
         int streamType,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        int channels,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
@@ -62,7 +62,7 @@
         int notificationFrames)
     : mStatus(NO_INIT)
 {
-    mStatus = set(streamType, sampleRate, format, channelCount,
+    mStatus = set(streamType, sampleRate, format, channels,
             frameCount, flags, cbf, user, notificationFrames, 0);
 }
 
@@ -70,7 +70,7 @@
         int streamType,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        int channels,
         const sp<IMemory>& sharedBuffer,
         uint32_t flags,
         callback_t cbf,
@@ -78,7 +78,7 @@
         int notificationFrames)
     : mStatus(NO_INIT)
 {
-    mStatus = set(streamType, sampleRate, format, channelCount,
+    mStatus = set(streamType, sampleRate, format, channels,
             0, flags, cbf, user, notificationFrames, sharedBuffer);
 }
 
@@ -97,6 +97,7 @@
         }
         mAudioTrack.clear();
         IPCThreadState::self()->flushCommands();
+        AudioSystem::releaseOutput(getOutput());
     }
 }
 
@@ -104,7 +105,7 @@
         int streamType,
         uint32_t sampleRate,
         int format,
-        int channelCount,
+        int channels,
         int frameCount,
         uint32_t flags,
         callback_t cbf,
@@ -150,63 +151,84 @@
     if (format == 0) {
         format = AudioSystem::PCM_16_BIT;
     }
-    if (channelCount == 0) {
-        channelCount = 2;
+    if (channels == 0) {
+        channels = AudioSystem::CHANNEL_OUT_STEREO;
     }
 
     // validate parameters
-    if (((format != AudioSystem::PCM_8_BIT) || sharedBuffer != 0) &&
-        (format != AudioSystem::PCM_16_BIT)) {
+    if (!AudioSystem::isValidFormat(format)) {
         LOGE("Invalid format");
         return BAD_VALUE;
     }
-    if (channelCount != 1 && channelCount != 2) {
-        LOGE("Invalid channel number");
+
+    // force direct flag if format is not linear PCM
+    if (!AudioSystem::isLinearPCM(format)) {
+        flags |= AudioSystem::OUTPUT_FLAG_DIRECT;
+    }
+
+    if (!AudioSystem::isOutputChannel(channels)) {
+        LOGE("Invalid channel mask");
+        return BAD_VALUE;
+    }
+    uint32_t channelCount = AudioSystem::popCount(channels);
+
+    audio_io_handle_t output = AudioSystem::getOutput((AudioSystem::stream_type)streamType,
+            sampleRate, format, channels, (AudioSystem::output_flags)flags);
+
+    if (output == 0) {
+        LOGE("Could not get audio output for stream type %d", streamType);
         return BAD_VALUE;
     }
 
-    // Ensure that buffer depth covers at least audio hardware latency
-    uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
-    if (minBufCount < 2) minBufCount = 2;
-
-    // When playing from shared buffer, playback will start even if last audioflinger
-    // block is partly filled.
-    if (sharedBuffer != 0 && minBufCount > 1) {
-        minBufCount--;
-    }
-
-    int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
-
-    if (sharedBuffer == 0) {
-        if (frameCount == 0) {
-            frameCount = minFrameCount;
-        }
-        if (notificationFrames == 0) {
-            notificationFrames = frameCount/2;
-        }
-        // Make sure that application is notified with sufficient margin
-        // before underrun
-        if (notificationFrames > frameCount/2) {
-            notificationFrames = frameCount/2;
+    if (!AudioSystem::isLinearPCM(format)) {
+        if (sharedBuffer != 0) {
+            frameCount = sharedBuffer->size();
         }
     } else {
-        // Ensure that buffer alignment matches channelcount
-        if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
-            LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
-            return BAD_VALUE;
-        }
-        frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
-    }
+        // Ensure that buffer depth covers at least audio hardware latency
+        uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
+        if (minBufCount < 2) minBufCount = 2;
 
-    if (frameCount < minFrameCount) {
-      LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
-      return BAD_VALUE;
+        int minFrameCount = (afFrameCount*sampleRate*minBufCount)/afSampleRate;
+
+        if (sharedBuffer == 0) {
+            if (frameCount == 0) {
+                frameCount = minFrameCount;
+            }
+            if (notificationFrames == 0) {
+                notificationFrames = frameCount/2;
+            }
+            // Make sure that application is notified with sufficient margin
+            // before underrun
+            if (notificationFrames > frameCount/2) {
+                notificationFrames = frameCount/2;
+            }
+            if (frameCount < minFrameCount) {
+              LOGE("Invalid buffer size: minFrameCount %d, frameCount %d", minFrameCount, frameCount);
+              return BAD_VALUE;
+            }
+        } else {
+            // Ensure that buffer alignment matches channelcount
+            if (((uint32_t)sharedBuffer->pointer() & (channelCount | 1)) != 0) {
+                LOGE("Invalid buffer alignement: address %p, channelCount %d", sharedBuffer->pointer(), channelCount);
+                return BAD_VALUE;
+            }
+            frameCount = sharedBuffer->size()/channelCount/sizeof(int16_t);
+        }
     }
 
     // create the track
     status_t status;
     sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
-                streamType, sampleRate, format, channelCount, frameCount, flags, sharedBuffer, &status);
+                                                      streamType,
+                                                      sampleRate,
+                                                      format,
+                                                      channelCount,
+                                                      frameCount,
+                                                      ((uint16_t)flags) << 16,
+                                                      sharedBuffer,
+                                                      output,
+                                                      &status);
 
     if (track == 0) {
         LOGE("AudioFlinger could not create track, status: %d", status);
@@ -245,6 +267,7 @@
     mVolume[RIGHT] = 1.0f;
     mStreamType = streamType;
     mFormat = format;
+    mChannels = channels;
     mChannelCount = channelCount;
     mSharedBuffer = sharedBuffer;
     mMuted = false;
@@ -259,6 +282,7 @@
     mMarkerReached = false;
     mNewPosition = 0;
     mUpdatePeriod = 0;
+    mFlags = flags;
 
     return NO_ERROR;
 }
@@ -297,7 +321,11 @@
 
 int AudioTrack::frameSize() const
 {
-    return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
+    } else {
+        return sizeof(uint8_t);
+    }
 }
 
 sp<IMemory>& AudioTrack::sharedBuffer()
@@ -323,6 +351,7 @@
      }
 
     if (android_atomic_or(1, &mActive) == 0) {
+        AudioSystem::startOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
         mNewPosition = mCblk->server + mUpdatePeriod;
         mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
         mCblk->waitTimeMs = 0;
@@ -367,6 +396,7 @@
         } else {
             setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
         }
+        AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
     }
 
     if (t != 0) {
@@ -382,12 +412,12 @@
 void AudioTrack::flush()
 {
     LOGV("flush");
-    
+
     // clear playback marker and periodic update counter
     mMarkerPosition = 0;
     mMarkerReached = false;
     mUpdatePeriod = 0;
-    
+
 
     if (!mActive) {
         mAudioTrack->flush();
@@ -403,6 +433,7 @@
     if (android_atomic_and(~1, &mActive) == 1) {
         mActive = 0;
         mAudioTrack->pause();
+        AudioSystem::stopOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
     }
 }
 
@@ -455,7 +486,6 @@
 {
     audio_track_cblk_t* cblk = mCblk;
 
-
     Mutex::Autolock _l(cblk->lock);
 
     if (loopCount == 0) {
@@ -476,7 +506,7 @@
         LOGE("setLoop invalid value: loop markers beyond data: loopStart %d, loopEnd %d, framecount %d",
             loopStart, loopEnd, mFrameCount);
         return BAD_VALUE;
-    }   
+    }
 
     cblk->loopStart = loopStart;
     cblk->loopEnd = loopEnd;
@@ -555,7 +585,7 @@
 
     mCblk->server = position;
     mCblk->forceReady = 1;
-    
+
     return NO_ERROR;
 }
 
@@ -571,7 +601,7 @@
 status_t AudioTrack::reload()
 {
     if (!stopped()) return INVALID_OPERATION;
-    
+
     flush();
 
     mCblk->stepUser(mFrameCount);
@@ -579,6 +609,12 @@
     return NO_ERROR;
 }
 
+audio_io_handle_t AudioTrack::getOutput()
+{
+    return AudioSystem::getOutput((AudioSystem::stream_type)mStreamType,
+            mCblk->sampleRate, mFormat, mChannels, (AudioSystem::output_flags)mFlags);
+}
+
 // -------------------------------------------------------------------------
 
 status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
@@ -608,7 +644,7 @@
                 return WOULD_BLOCK;
             timeout = 0;
             result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
-            if (__builtin_expect(result!=NO_ERROR, false)) { 
+            if (__builtin_expect(result!=NO_ERROR, false)) {
                 cblk->waitTimeMs += waitTimeMs;
                 if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
                     // timing out when a loop has been set and we have already written upto loop end
@@ -616,7 +652,7 @@
                     if (cblk->user < cblk->loopEnd) {
                         LOGW(   "obtainBuffer timed out (is the CPU pegged?) %p "
                                 "user=%08x, server=%08x", this, cblk->user, cblk->server);
-                        //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140) 
+                        //unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
                         cblk->lock.unlock();
                         mAudioTrack->start();
                         cblk->lock.lock();
@@ -624,7 +660,7 @@
                     }
                     cblk->waitTimeMs = 0;
                 }
-                
+
                 if (--waitCount == 0) {
                     return TIMED_OUT;
                 }
@@ -636,7 +672,7 @@
     }
 
     cblk->waitTimeMs = 0;
-    
+
     if (framesReq > framesAvail) {
         framesReq = framesAvail;
     }
@@ -653,12 +689,16 @@
         "but didn't need to be locked. We recovered, but "
         "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
 
-    audioBuffer->flags       = mMuted ? Buffer::MUTE : 0;
-    audioBuffer->channelCount= mChannelCount;
-    audioBuffer->format      = AudioSystem::PCM_16_BIT;
-    audioBuffer->frameCount  = framesReq;
-    audioBuffer->size = framesReq*mChannelCount*sizeof(int16_t);
-    audioBuffer->raw         = (int8_t *)cblk->buffer(u);
+    audioBuffer->flags = mMuted ? Buffer::MUTE : 0;
+    audioBuffer->channelCount = mChannelCount;
+    audioBuffer->frameCount = framesReq;
+    audioBuffer->size = framesReq * cblk->frameSize;
+    if (AudioSystem::isLinearPCM(mFormat)) {
+        audioBuffer->format = AudioSystem::PCM_16_BIT;
+    } else {
+        audioBuffer->format = mFormat;
+    }
+    audioBuffer->raw = (int8_t *)cblk->buffer(u);
     active = mActive;
     return active ? status_t(NO_ERROR) : status_t(STOPPED);
 }
@@ -690,10 +730,8 @@
     Buffer audioBuffer;
 
     do {
-        audioBuffer.frameCount = userSize/mChannelCount;
-        if (mFormat == AudioSystem::PCM_16_BIT) {
-            audioBuffer.frameCount >>= 1;
-        }
+        audioBuffer.frameCount = userSize/frameSize();
+
         // Calling obtainBuffer() with a negative wait count causes
         // an (almost) infinite wait time.
         status_t err = obtainBuffer(&audioBuffer, -1);
@@ -705,6 +743,7 @@
         }
 
         size_t toWrite;
+
         if (mFormat == AudioSystem::PCM_8_BIT) {
             // Divide capacity by 2 to take expansion into account
             toWrite = audioBuffer.size>>1;
@@ -742,13 +781,13 @@
         if (mCblk->flowControlFlag == 0) {
             mCbf(EVENT_UNDERRUN, mUserData, 0);
             if (mCblk->server == mCblk->frameCount) {
-                mCbf(EVENT_BUFFER_END, mUserData, 0);                
+                mCbf(EVENT_BUFFER_END, mUserData, 0);
             }
             mCblk->flowControlFlag = 1;
             if (mSharedBuffer != 0) return false;
         }
     }
-    
+
     // Manage loop end callback
     while (mLoopCount > mCblk->loopCount) {
         int loopCount = -1;
@@ -767,7 +806,7 @@
     }
 
     // Manage new position callback
-    if(mUpdatePeriod > 0) {
+    if (mUpdatePeriod > 0) {
         while (mCblk->server >= mNewPosition) {
             mCbf(EVENT_NEW_POS, mUserData, (void *)&mNewPosition);
             mNewPosition += mUpdatePeriod;
@@ -784,10 +823,10 @@
     do {
 
         audioBuffer.frameCount = frames;
-        
-        // Calling obtainBuffer() with a wait count of 1 
-        // limits wait time to WAIT_PERIOD_MS. This prevents from being 
-        // stuck here not being able to handle timed events (position, markers, loops). 
+
+        // Calling obtainBuffer() with a wait count of 1
+        // limits wait time to WAIT_PERIOD_MS. This prevents from being
+        // stuck here not being able to handle timed events (position, markers, loops).
         status_t err = obtainBuffer(&audioBuffer, 1);
         if (err < NO_ERROR) {
             if (err != TIMED_OUT) {
@@ -832,7 +871,11 @@
         }
 
         audioBuffer.size = writtenSize;
-        audioBuffer.frameCount = writtenSize/mChannelCount/sizeof(int16_t);
+        // NOTE: mCblk->frameSize is not equal to AudioTrack::frameSize() for
+        // 8 bit PCM data: in this case,  mCblk->frameSize is based on a sampel size of
+        // 16 bit.
+        audioBuffer.frameCount = writtenSize/mCblk->frameSize;
+
         frames -= audioBuffer.frameCount;
 
         releaseBuffer(&audioBuffer);
@@ -949,7 +992,7 @@
         // we switch to normal obtainBuffer() timeout period
         if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
             bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1;
-        }        
+        }
         // It is possible that we receive a flush()
         // while the mixer is processing a block: in this case,
         // stepServer() is called After the flush() has reset u & s and
@@ -981,7 +1024,7 @@
 
 void* audio_track_cblk_t::buffer(uint32_t offset) const
 {
-    return (int16_t *)this->buffers + (offset-userBase)*this->channels;
+    return (int8_t *)this->buffers + (offset - userBase) * this->frameSize;
 }
 
 uint32_t audio_track_cblk_t::framesAvailable()