Merge "set AAC MPEG version to MPEG-2"
diff --git a/include/media/nbaio/NBAIO.h b/include/media/nbaio/NBAIO.h
index 9c9721a..56896b9 100644
--- a/include/media/nbaio/NBAIO.h
+++ b/include/media/nbaio/NBAIO.h
@@ -52,7 +52,10 @@
 // the combinations that are actually needed within AudioFlinger.  If the list of combinations grows
 // too large, then this decision should be re-visited.
 // Sample rate and channel count are explicit, PCM interleaved 16-bit is assumed.
-typedef unsigned NBAIO_Format;
+struct NBAIO_Format {
+//private:
+    unsigned    mPacked;
+};
 
 extern const NBAIO_Format Format_Invalid;
 
@@ -60,9 +63,11 @@
 size_t Format_frameSize(const NBAIO_Format& format);
 
 // Return the frame size of an NBAIO_Format as a bit shift
-size_t Format_frameBitShift(const NBAIO_Format& format);
+// or -1 if frame size is not a power of 2
+int Format_frameBitShift(const NBAIO_Format& format);
 
 // Convert a sample rate in Hz and channel count to an NBAIO_Format
+// FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT
 NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount);
 
 // Return the sample rate in Hz of an NBAIO_Format
@@ -76,6 +81,12 @@
 typedef ssize_t (*readVia_t)(void *user, const void *buffer,
                              size_t count, int64_t readPTS);
 
+// Check whether an NBAIO_Format is valid
+bool Format_isValid(const NBAIO_Format& format);
+
+// Compare two NBAIO_Format values
+bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2);
+
 // Abstract class (interface) representing a data port.
 class NBAIO_Port : public RefBase {
 
diff --git a/media/libnbaio/AudioBufferProviderSource.cpp b/media/libnbaio/AudioBufferProviderSource.cpp
index e952a00..4a69104 100644
--- a/media/libnbaio/AudioBufferProviderSource.cpp
+++ b/media/libnbaio/AudioBufferProviderSource.cpp
@@ -28,7 +28,7 @@
     NBAIO_Source(format), mProvider(provider), mConsumed(0)
 {
     ALOG_ASSERT(provider != NULL);
-    ALOG_ASSERT(format != Format_Invalid);
+    ALOG_ASSERT(Format_isValid(format));
 }
 
 AudioBufferProviderSource::~AudioBufferProviderSource()
diff --git a/media/libnbaio/AudioStreamInSource.cpp b/media/libnbaio/AudioStreamInSource.cpp
index 05273f6..ae8fac8 100644
--- a/media/libnbaio/AudioStreamInSource.cpp
+++ b/media/libnbaio/AudioStreamInSource.cpp
@@ -40,7 +40,7 @@
 ssize_t AudioStreamInSource::negotiate(const NBAIO_Format offers[], size_t numOffers,
                                       NBAIO_Format counterOffers[], size_t& numCounterOffers)
 {
-    if (mFormat == Format_Invalid) {
+    if (!Format_isValid(mFormat)) {
         mStreamBufferSizeBytes = mStream->common.get_buffer_size(&mStream->common);
         audio_format_t streamFormat = mStream->common.get_format(&mStream->common);
         if (streamFormat == AUDIO_FORMAT_PCM_16_BIT) {
@@ -67,7 +67,7 @@
 
 ssize_t AudioStreamInSource::read(void *buffer, size_t count)
 {
-    if (CC_UNLIKELY(mFormat == Format_Invalid)) {
+    if (CC_UNLIKELY(!Format_isValid(mFormat))) {
         return NEGOTIATE;
     }
     ssize_t bytesRead = mStream->read(mStream, buffer, count << mBitShift);
diff --git a/media/libnbaio/AudioStreamOutSink.cpp b/media/libnbaio/AudioStreamOutSink.cpp
index e4341d7..aa9810e 100644
--- a/media/libnbaio/AudioStreamOutSink.cpp
+++ b/media/libnbaio/AudioStreamOutSink.cpp
@@ -37,7 +37,7 @@
 ssize_t AudioStreamOutSink::negotiate(const NBAIO_Format offers[], size_t numOffers,
                                       NBAIO_Format counterOffers[], size_t& numCounterOffers)
 {
-    if (mFormat == Format_Invalid) {
+    if (!Format_isValid(mFormat)) {
         mStreamBufferSizeBytes = mStream->common.get_buffer_size(&mStream->common);
         audio_format_t streamFormat = mStream->common.get_format(&mStream->common);
         if (streamFormat == AUDIO_FORMAT_PCM_16_BIT) {
@@ -56,7 +56,7 @@
     if (!mNegotiated) {
         return NEGOTIATE;
     }
-    ALOG_ASSERT(mFormat != Format_Invalid);
+    ALOG_ASSERT(Format_isValid(mFormat));
     ssize_t ret = mStream->write(mStream, buffer, count << mBitShift);
     if (ret > 0) {
         ret >>= mBitShift;
diff --git a/media/libnbaio/NBAIO.cpp b/media/libnbaio/NBAIO.cpp
index 8a8155d..51514de 100644
--- a/media/libnbaio/NBAIO.cpp
+++ b/media/libnbaio/NBAIO.cpp
@@ -24,13 +24,16 @@
 
 size_t Format_frameSize(const NBAIO_Format& format)
 {
+    // FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT
     return Format_channelCount(format) * sizeof(short);
 }
 
-size_t Format_frameBitShift(const NBAIO_Format& format)
+int Format_frameBitShift(const NBAIO_Format& format)
 {
+    // FIXME The sample format is hard-coded to AUDIO_FORMAT_PCM_16_BIT
     // sizeof(short) == 2, so frame size == 1 << channels
     return Format_channelCount(format);
+    // FIXME must return -1 for non-power of 2
 }
 
 const NBAIO_Format Format_Invalid = { 0 };
@@ -55,10 +58,10 @@
 
 unsigned Format_sampleRate(const NBAIO_Format& format)
 {
-    if (format == Format_Invalid) {
+    if (!Format_isValid(format)) {
         return 0;
     }
-    switch (format & Format_SR_Mask) {
+    switch (format.mPacked & Format_SR_Mask) {
     case Format_SR_8000:
         return 8000;
     case Format_SR_11025:
@@ -82,10 +85,10 @@
 
 unsigned Format_channelCount(const NBAIO_Format& format)
 {
-    if (format == Format_Invalid) {
+    if (!Format_isValid(format)) {
         return 0;
     }
-    switch (format & Format_C_Mask) {
+    switch (format.mPacked & Format_C_Mask) {
     case Format_C_1:
         return 1;
     case Format_C_2:
@@ -97,7 +100,7 @@
 
 NBAIO_Format Format_from_SR_C(unsigned sampleRate, unsigned channelCount)
 {
-    NBAIO_Format format;
+    unsigned format;
     switch (sampleRate) {
     case 8000:
         format = Format_SR_8000;
@@ -136,7 +139,9 @@
     default:
         return Format_Invalid;
     }
-    return format;
+    NBAIO_Format ret;
+    ret.mPacked = format;
+    return ret;
 }
 
 // This is a default implementation; it is expected that subclasses will optimize this.
@@ -218,9 +223,9 @@
 {
     ALOGV("negotiate offers=%p numOffers=%u countersOffers=%p numCounterOffers=%u",
             offers, numOffers, counterOffers, numCounterOffers);
-    if (mFormat != Format_Invalid) {
+    if (Format_isValid(mFormat)) {
         for (size_t i = 0; i < numOffers; ++i) {
-            if (offers[i] == mFormat) {
+            if (Format_isEqual(offers[i], mFormat)) {
                 mNegotiated = true;
                 return i;
             }
@@ -235,4 +240,14 @@
     return (ssize_t) NEGOTIATE;
 }
 
+bool Format_isValid(const NBAIO_Format& format)
+{
+    return format.mPacked != Format_Invalid.mPacked;
+}
+
+bool Format_isEqual(const NBAIO_Format& format1, const NBAIO_Format& format2)
+{
+    return format1.mPacked == format2.mPacked;
+}
+
 }   // namespace android
diff --git a/media/libstagefright/http/Android.mk b/media/libstagefright/http/Android.mk
index baef9ab..a6b481f 100644
--- a/media/libstagefright/http/Android.mk
+++ b/media/libstagefright/http/Android.mk
@@ -1,5 +1,7 @@
 LOCAL_PATH:= $(call my-dir)
 
+ifneq ($(TARGET_BUILD_PDK), true)
+
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=       \
@@ -20,3 +22,5 @@
 LOCAL_CFLAGS += -Wno-multichar
 
 include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 7c73b19..81f046f 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1783,7 +1783,7 @@
                                         popcount(inStream->common.get_channels(&inStream->common)));
         if (!mTeeSinkInputEnabled) {
             kind = TEE_SINK_NO;
-        } else if (format == Format_Invalid) {
+        } else if (!Format_isValid(format)) {
             kind = TEE_SINK_NO;
         } else if (mRecordTeeSink == 0) {
             kind = TEE_SINK_NEW;
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 7126e92..28b9d77 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -239,7 +239,7 @@
                 dumpState->mSampleRate = sampleRate;
             }
 
-            if ((format != previousFormat) || (frameCount != previous->mFrameCount)) {
+            if ((!Format_isEqual(format, previousFormat)) || (frameCount != previous->mFrameCount)) {
                 // FIXME to avoid priority inversion, don't delete here
                 delete mixer;
                 mixer = NULL;
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 4b6c74d..6600161 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -94,6 +94,8 @@
     bool isReady() const;
     void setPaused() { mState = PAUSED; }
     void reset();
+    bool isFlushPending() const { return mFlushHwPending; }
+    void flushAck();
 
     bool isOutputTrack() const {
         return (mStreamType == AUDIO_STREAM_CNT);
@@ -155,6 +157,7 @@
     bool                mIsInvalid; // non-resettable latch, set by invalidate()
     AudioTrackServerProxy*  mAudioTrackServerProxy;
     bool                mResumeToStopping; // track was paused in stopping state.
+    bool                mFlushHwPending; // track requests for thread flush
 };  // end of Track
 
 class TimedTrack : public Track {
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 24df473..7de688e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1490,9 +1490,7 @@
         status = NO_ERROR;
     }
 
-    ALOGV("signal playback thread");
-    broadcast_l();
-
+    onAddNewTrack_l();
     return status;
 }
 
@@ -2727,12 +2725,6 @@
     PlaybackThread::threadLoop_standby();
 }
 
-// Empty implementation for standard mixer
-// Overridden for offloaded playback
-void AudioFlinger::PlaybackThread::flushOutput_l()
-{
-}
-
 bool AudioFlinger::PlaybackThread::waitingAsyncCallback_l()
 {
     return false;
@@ -2764,6 +2756,12 @@
     }
 }
 
+void AudioFlinger::PlaybackThread::onAddNewTrack_l()
+{
+    ALOGV("signal playback thread");
+    broadcast_l();
+}
+
 void AudioFlinger::MixerThread::threadLoop_mix()
 {
     // obtain the presentation timestamp of the next output buffer
@@ -4003,6 +4001,17 @@
         sp<Track> l = mLatestActiveTrack.promote();
         bool last = l.get() == track;
 
+        if (track->isInvalid()) {
+            ALOGW("An invalidated track shouldn't be in active list");
+            tracksToRemove->add(track);
+            continue;
+        }
+
+        if (track->mState == TrackBase::IDLE) {
+            ALOGW("An idle track shouldn't be in active list");
+            continue;
+        }
+
         if (track->isPausing()) {
             track->setPaused();
             if (last) {
@@ -4021,6 +4030,11 @@
                 mBytesRemaining = 0;    // stop writing
             }
             tracksToRemove->add(track);
+        } else if (track->isFlushPending()) {
+            track->flushAck();
+            if (last) {
+                mFlushPending = true;
+            }
         } else if (track->framesReady() && track->isReady() &&
                 !track->isPaused() && !track->isTerminated() && !track->isStopping_2()) {
             ALOGVV("OffloadThread: track %d s=%08x [OK]", track->name(), cblk->mServer);
@@ -4070,7 +4084,6 @@
                         // seek when resuming.
                         if (previousTrack->sessionId() != track->sessionId()) {
                             previousTrack->invalidate();
-                            mFlushPending = true;
                         }
                     }
                 }
@@ -4146,9 +4159,6 @@
     // if resume is received before pause is executed.
     if (!mStandby && (doHwPause || (mFlushPending && !mHwPaused && (count != 0)))) {
         mOutput->stream->pause(mOutput->stream);
-        if (!doHwPause) {
-            doHwResume = true;
-        }
     }
     if (mFlushPending) {
         flushHw_l();
@@ -4164,11 +4174,6 @@
     return mixerStatus;
 }
 
-void AudioFlinger::OffloadThread::flushOutput_l()
-{
-    mFlushPending = true;
-}
-
 // must be called with thread mutex locked
 bool AudioFlinger::OffloadThread::waitingAsyncCallback_l()
 {
@@ -4209,6 +4214,8 @@
     mBytesRemaining = 0;
     mPausedWriteLength = 0;
     mPausedBytesRemaining = 0;
+    mHwPaused = false;
+
     if (mUseAsyncWrite) {
         // discard any pending drain or write ack by incrementing sequence
         mWriteAckSequence = (mWriteAckSequence + 2) & ~1;
@@ -4219,6 +4226,18 @@
     }
 }
 
+void AudioFlinger::OffloadThread::onAddNewTrack_l()
+{
+    sp<Track> previousTrack = mPreviousTrack.promote();
+    sp<Track> latestTrack = mLatestActiveTrack.promote();
+
+    if (previousTrack != 0 && latestTrack != 0 &&
+        (previousTrack->sessionId() != latestTrack->sessionId())) {
+        mFlushPending = true;
+    }
+    PlaybackThread::onAddNewTrack_l();
+}
+
 // ----------------------------------------------------------------------------
 
 AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 1745ea1..9bf59d8 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -65,7 +65,7 @@
     class IoConfigEvent : public ConfigEvent {
     public:
         IoConfigEvent(int event, int param) :
-            ConfigEvent(CFG_EVENT_IO), mEvent(event), mParam(event) {}
+            ConfigEvent(CFG_EVENT_IO), mEvent(event), mParam(param) {}
         virtual ~IoConfigEvent() {}
 
                 int event() const { return mEvent; }
@@ -394,7 +394,7 @@
     virtual     bool        waitingAsyncCallback();
     virtual     bool        waitingAsyncCallback_l();
     virtual     bool        shouldStandby_l();
-
+    virtual     void        onAddNewTrack_l();
 
     // ThreadBase virtuals
     virtual     void        preExit();
@@ -631,7 +631,6 @@
 protected:
                 // accessed by both binder threads and within threadLoop(), lock on mutex needed
                 unsigned    mFastTrackAvailMask;    // bit i set if fast track [i] is available
-    virtual     void        flushOutput_l();
 
 private:
     // timestamp latch:
@@ -750,11 +749,11 @@
     // threadLoop snippets
     virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
     virtual     void        threadLoop_exit();
-    virtual     void        flushOutput_l();
 
     virtual     bool        waitingAsyncCallback();
     virtual     bool        waitingAsyncCallback_l();
     virtual     bool        shouldStandby_l();
+    virtual     void        onAddNewTrack_l();
 
 private:
                 void        flushHw_l();
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index ecedca9..8004b99 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -146,7 +146,7 @@
 #ifdef TEE_SINK
         if (mTeeSinkTrackEnabled) {
             NBAIO_Format pipeFormat = Format_from_SR_C(mSampleRate, mChannelCount);
-            if (pipeFormat != Format_Invalid) {
+            if (Format_isValid(pipeFormat)) {
                 Pipe *pipe = new Pipe(mTeeSinkTrackFrames, pipeFormat);
                 size_t numCounterOffers = 0;
                 const NBAIO_Format offers[1] = {pipeFormat};
@@ -347,7 +347,8 @@
     mCachedVolume(1.0),
     mIsInvalid(false),
     mAudioTrackServerProxy(NULL),
-    mResumeToStopping(false)
+    mResumeToStopping(false),
+    mFlushHwPending(false)
 {
     if (mCblk != NULL) {
         if (sharedBuffer == 0) {
@@ -731,6 +732,7 @@
                 mRetryCount = PlaybackThread::kMaxTrackRetriesOffload;
             }
 
+            mFlushHwPending = true;
             mResumeToStopping = false;
         } else {
             if (mState != STOPPING_1 && mState != STOPPING_2 && mState != STOPPED &&
@@ -751,11 +753,19 @@
         // Prevent flush being lost if the track is flushed and then resumed
         // before mixer thread can run. This is important when offloading
         // because the hardware buffer could hold a large amount of audio
-        playbackThread->flushOutput_l();
         playbackThread->broadcast_l();
     }
 }
 
+// must be called with thread lock held
+void AudioFlinger::PlaybackThread::Track::flushAck()
+{
+    if (!isOffloaded())
+        return;
+
+    mFlushHwPending = false;
+}
+
 void AudioFlinger::PlaybackThread::Track::reset()
 {
     // Do not reset twice to avoid discarding data written just after a flush and before