am 9e3d9575: Merge "stagefright aacenc: Add prototypes for arm specific implementations of functions"

* commit '9e3d957599c76ba19e23fd25b75ccc02d54efe3e':
  stagefright aacenc: Add prototypes for arm specific implementations of functions
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 7a2d7b3..d0cb7ff 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -1841,6 +1841,10 @@
         return;
     }
     mAudioStatusEventPending = true;
+    // Do not honor delay when looping in order to limit audio gap
+    if (mFlags & (LOOPING | AUTO_LOOPING)) {
+        delayUs = 0;
+    }
     mQueue.postEventWithDelay(mCheckAudioStatusEvent, delayUs);
 }
 
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 30f8e12..5a46e44 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1832,7 +1832,7 @@
 
 AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device)
     :   PlaybackThread(audioFlinger, output, id, device),
-        mAudioMixer(0)
+        mAudioMixer(0), mPrevMixerStatus(MIXER_IDLE)
 {
     mType = ThreadBase::MIXER;
     mAudioMixer = new AudioMixer(mFrameCount, mSampleRate);
@@ -1945,6 +1945,7 @@
                     ALOGV("MixerThread %p TID %d waking up\n", this, gettid());
                     acquireWakeLock_l();
 
+                    mPrevMixerStatus = MIXER_IDLE;
                     if (mMasterMute == false) {
                         char value[PROPERTY_VALUE_MAX];
                         property_get("ro.audio.silent", value, "0");
@@ -1972,11 +1973,14 @@
         if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
             // mix buffers...
             mAudioMixer->process();
-            sleepTime = 0;
-            // increase sleep time progressively when application underrun condition clears
-            if (sleepTimeShift > 0) {
+            // increase sleep time progressively when application underrun condition clears.
+            // Only increase sleep time if the mixer is ready for two consecutive times to avoid
+            // that a steady state of alternating ready/not ready conditions keeps the sleep time
+            // such that we would underrun the audio HAL.
+            if ((sleepTime == 0) && (sleepTimeShift > 0)) {
                 sleepTimeShift--;
             }
+            sleepTime = 0;
             standbyTime = systemTime() + kStandbyTimeInNsecs;
             //TODO: delay standby when effects have a tail
         } else {
@@ -2103,15 +2107,23 @@
         // make sure that we have enough frames to mix one full buffer.
         // enforce this condition only once to enable draining the buffer in case the client
         // app does not call stop() and relies on underrun to stop:
-        // hence the test on (track->mRetryCount >= kMaxTrackRetries) meaning the track was mixed
+        // hence the test on (mPrevMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed
         // during last round
         uint32_t minFrames = 1;
         if (!track->isStopped() && !track->isPausing() &&
-                (track->mRetryCount >= kMaxTrackRetries)) {
+                (mPrevMixerStatus == MIXER_TRACKS_READY)) {
             if (t->sampleRate() == (int)mSampleRate) {
                 minFrames = mFrameCount;
             } else {
-                minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1;
+                // +1 for rounding and +1 for additional sample needed for interpolation
+                minFrames = (mFrameCount * t->sampleRate()) / mSampleRate + 1 + 1;
+                // add frames already consumed but not yet released by the resampler
+                // because cblk->framesReady() will  include these frames
+                minFrames += mAudioMixer->getUnreleasedFrames(track->name());
+                // the minimum track buffer size is normally twice the number of frames necessary
+                // to fill one buffer and the resampler should not leave more than one buffer worth
+                // of unreleased frames after each pass, but just in case...
+                LOG_ASSERT(minFrames <= cblk->frameCount);
             }
         }
         if ((cblk->framesReady() >= minFrames) && track->isReady() &&
@@ -2221,7 +2233,13 @@
 
             // reset retry count
             track->mRetryCount = kMaxTrackRetries;
-            mixerStatus = MIXER_TRACKS_READY;
+            // If one track is ready, set the mixer ready if:
+            //  - the mixer was not ready during previous round OR
+            //  - no other track is not ready
+            if (mPrevMixerStatus != MIXER_TRACKS_READY ||
+                    mixerStatus != MIXER_TRACKS_ENABLED) {
+                mixerStatus = MIXER_TRACKS_READY;
+            }
         } else {
             //ALOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", track->name(), cblk->user, cblk->server, this);
             if (track->isStopped()) {
@@ -2239,7 +2257,11 @@
                     tracksToRemove->add(track);
                     // indicate to client process that the track was disabled because of underrun
                     android_atomic_or(CBLK_DISABLED_ON, &cblk->flags);
-                } else if (mixerStatus != MIXER_TRACKS_READY) {
+                // If one track is not ready, mark the mixer also not ready if:
+                //  - the mixer was ready during previous round OR
+                //  - no other track is ready
+                } else if (mPrevMixerStatus == MIXER_TRACKS_READY ||
+                                mixerStatus != MIXER_TRACKS_READY) {
                     mixerStatus = MIXER_TRACKS_ENABLED;
                 }
             }
@@ -2273,6 +2295,7 @@
         memset(mMixBuffer, 0, mFrameCount * mChannelCount * sizeof(int16_t));
     }
 
+    mPrevMixerStatus = mixerStatus;
     return mixerStatus;
 }
 
@@ -3008,6 +3031,7 @@
                     ALOGV("DuplicatingThread %p TID %d waking up\n", this, gettid());
                     acquireWakeLock_l();
 
+                    mPrevMixerStatus = MIXER_IDLE;
                     if (mMasterMute == false) {
                         char value[PROPERTY_VALUE_MAX];
                         property_get("ro.audio.silent", value, "0");
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 6cafa7e..9bd2c7f 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -836,7 +836,9 @@
         virtual     uint32_t    idleSleepTimeUs();
         virtual     uint32_t    suspendSleepTimeUs();
 
-        AudioMixer*                     mAudioMixer;
+                    AudioMixer* mAudioMixer;
+                    uint32_t    mPrevMixerStatus; // previous status (mixer_state) returned by
+                                                  // prepareTracks_l()
     };
 
     class DirectOutputThread : public PlaybackThread {
diff --git a/services/audioflinger/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index dcb0b13..9dda256 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -331,6 +331,23 @@
     }
 }
 
+size_t AudioMixer::track_t::getUnreleasedFrames()
+{
+    if (resampler != NULL) {
+        return resampler->getUnreleasedFrames();
+    }
+    return 0;
+}
+
+size_t AudioMixer::getUnreleasedFrames(int name)
+{
+    name -= TRACK0;
+    if (uint32_t(name) < MAX_NUM_TRACKS) {
+        track_t& track(mState.tracks[name]);
+        return track.getUnreleasedFrames();
+    }
+    return 0;
+}
 
 status_t AudioMixer::setBufferProvider(AudioBufferProvider* buffer)
 {
diff --git a/services/audioflinger/AudioMixer.h b/services/audioflinger/AudioMixer.h
index 75c9170..0137185 100644
--- a/services/audioflinger/AudioMixer.h
+++ b/services/audioflinger/AudioMixer.h
@@ -91,6 +91,8 @@
 
     static void ditherAndClamp(int32_t* out, int32_t const *sums, size_t c);
 
+    size_t      getUnreleasedFrames(int name);
+
 private:
 
     enum {
@@ -167,6 +169,7 @@
         bool        doesResample() const;
         void        resetResampler();
         void        adjustVolumeRamp(bool aux);
+        size_t      getUnreleasedFrames();
     };
 
     // pad to 32-bytes to fill cache line
diff --git a/services/audioflinger/AudioResampler.h b/services/audioflinger/AudioResampler.h
index 9f06c1c..ffa690a 100644
--- a/services/audioflinger/AudioResampler.h
+++ b/services/audioflinger/AudioResampler.h
@@ -54,6 +54,7 @@
             AudioBufferProvider* provider) = 0;
 
     virtual void reset();
+    virtual size_t getUnreleasedFrames() { return mInputIndex; }
 
 protected:
     // number of bits for phase fraction - 30 bits allows nearly 2x downsampling
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 6333bd8..918f31e 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -97,16 +97,6 @@
             setCameraFree(i);
         }
     }
-
-    // Read the system property to determine if we have to use the
-    // AUDIO_STREAM_ENFORCED_AUDIBLE type.
-    char value[PROPERTY_VALUE_MAX];
-    property_get("ro.camera.sound.forced", value, "0");
-    if (strcmp(value, "0") != 0) {
-        mAudioStreamType = AUDIO_STREAM_ENFORCED_AUDIBLE;
-    } else {
-        mAudioStreamType = AUDIO_STREAM_MUSIC;
-    }
 }
 
 CameraService::~CameraService() {
@@ -295,7 +285,7 @@
 MediaPlayer* CameraService::newMediaPlayer(const char *file) {
     MediaPlayer* mp = new MediaPlayer();
     if (mp->setDataSource(file, NULL) == NO_ERROR) {
-        mp->setAudioStreamType(mAudioStreamType);
+        mp->setAudioStreamType(AUDIO_STREAM_ENFORCED_AUDIBLE);
         mp->prepare();
     } else {
         ALOGE("Failed to load CameraService sounds: %s", file);
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index cdfbc56..bad41f5 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -76,7 +76,6 @@
     void                setCameraFree(int cameraId);
 
     // sounds
-    audio_stream_type_t mAudioStreamType;
     MediaPlayer*        newMediaPlayer(const char *file);
 
     Mutex               mSoundLock;