Merge "Use AudioRecord::record_flags consistently"
diff --git a/cmds/stagefright/codec.cpp b/cmds/stagefright/codec.cpp
index 0414b98..fea62cc 100644
--- a/cmds/stagefright/codec.cpp
+++ b/cmds/stagefright/codec.cpp
@@ -49,6 +49,7 @@
     size_t mCSDIndex;
     Vector<sp<ABuffer> > mInBuffers;
     Vector<sp<ABuffer> > mOutBuffers;
+    bool mSignalledInputEOS;
     bool mSawOutputEOS;
     int64_t mNumBuffersDecoded;
     int64_t mNumBytesDecoded;
@@ -127,6 +128,7 @@
         }
 
         state->mCSDIndex = 0;
+        state->mSignalledInputEOS = false;
         state->mSawOutputEOS = false;
 
         ALOGV("got %d pieces of codec specific data.", state->mCSD.size());
@@ -180,33 +182,7 @@
             status_t err = extractor->getSampleTrackIndex(&trackIndex);
 
             if (err != OK) {
-                ALOGV("signalling EOS.");
-
-                for (size_t i = 0; i < stateByTrack.size(); ++i) {
-                    CodecState *state = &stateByTrack.editValueAt(i);
-
-                    for (;;) {
-                        size_t index;
-                        err = state->mCodec->dequeueInputBuffer(&index, kTimeout);
-
-                        if (err == -EAGAIN) {
-                            continue;
-                        }
-
-                        CHECK_EQ(err, (status_t)OK);
-
-                        err = state->mCodec->queueInputBuffer(
-                                index,
-                                0 /* offset */,
-                                0 /* size */,
-                                0ll /* timeUs */,
-                                MediaCodec::BUFFER_FLAG_EOS);
-
-                        CHECK_EQ(err, (status_t)OK);
-                        break;
-                    }
-                }
-
+                ALOGV("saw input eos");
                 sawInputEOS = true;
             } else {
                 CodecState *state = &stateByTrack.editValueFor(trackIndex);
@@ -240,6 +216,33 @@
                     CHECK_EQ(err, -EAGAIN);
                 }
             }
+        } else {
+            for (size_t i = 0; i < stateByTrack.size(); ++i) {
+                CodecState *state = &stateByTrack.editValueAt(i);
+
+                if (!state->mSignalledInputEOS) {
+                    size_t index;
+                    status_t err =
+                        state->mCodec->dequeueInputBuffer(&index, kTimeout);
+
+                    if (err == OK) {
+                        ALOGV("signalling input EOS on track %d", i);
+
+                        err = state->mCodec->queueInputBuffer(
+                                index,
+                                0 /* offset */,
+                                0 /* size */,
+                                0ll /* timeUs */,
+                                MediaCodec::BUFFER_FLAG_EOS);
+
+                        CHECK_EQ(err, (status_t)OK);
+
+                        state->mSignalledInputEOS = true;
+                    } else {
+                        CHECK_EQ(err, -EAGAIN);
+                    }
+                }
+            }
         }
 
         bool sawOutputEOSOnAllTracks = true;
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index d54ab35..cc0a594 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -185,7 +185,7 @@
                                          audio_devices_t device);
 
     static uint32_t getStrategyForStream(audio_stream_type_t stream);
-    static uint32_t getDevicesForStream(audio_stream_type_t stream);
+    static audio_devices_t getDevicesForStream(audio_stream_type_t stream);
 
     static audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
     static status_t registerEffect(effect_descriptor_t *desc,
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index bdd7747..04c927a 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -79,7 +79,7 @@
                                           int *index,
                                           audio_devices_t device) = 0;
     virtual uint32_t getStrategyForStream(audio_stream_type_t stream) = 0;
-    virtual uint32_t getDevicesForStream(audio_stream_type_t stream) = 0;
+    virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream) = 0;
     virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc) = 0;
     virtual status_t registerEffect(effect_descriptor_t *desc,
                                     audio_io_handle_t io,
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index e0b186a..a1cbf0f 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -701,10 +701,10 @@
     return aps->getStrategyForStream(stream);
 }
 
-uint32_t AudioSystem::getDevicesForStream(audio_stream_type_t stream)
+audio_devices_t AudioSystem::getDevicesForStream(audio_stream_type_t stream)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
-    if (aps == 0) return 0;
+    if (aps == 0) return (audio_devices_t)0;
     return aps->getDevicesForStream(stream);
 }
 
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 99385aa..da7c124 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -267,13 +267,13 @@
         return reply.readInt32();
     }
 
-    virtual uint32_t getDevicesForStream(audio_stream_type_t stream)
+    virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream)
     {
         Parcel data, reply;
         data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
         data.writeInt32(static_cast <uint32_t>(stream));
         remote()->transact(GET_DEVICES_FOR_STREAM, data, &reply);
-        return (uint32_t) reply.readInt32();
+        return (audio_devices_t) reply.readInt32();
     }
 
     virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc)
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index 650b6c4..2b3cb1a 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -437,8 +437,11 @@
                         kKeyTime, &mPositionTimeMediaUs));
 
             mPositionTimeRealUs =
-                ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
+                -mLatencyUs + ((mNumFramesPlayed + size_done / mFrameSize) * 1000000)
                     / mSampleRate;
+            if (mPositionTimeRealUs < 0) {
+                mPositionTimeRealUs = 0;
+            }
 
             ALOGV("buffer->size() = %d, "
                  "mPositionTimeMediaUs=%.2f mPositionTimeRealUs=%.2f",
@@ -493,7 +496,9 @@
 int64_t AudioPlayer::getRealTimeUsLocked() const {
     CHECK(mStarted);
     CHECK_NE(mSampleRate, 0);
-    return -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
+    int64_t t = -mLatencyUs + (mNumFramesPlayed * 1000000) / mSampleRate;
+    if (t < 0) return 0;
+    return t;
 }
 
 int64_t AudioPlayer::getMediaTimeUs() {
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index b21e86a..9e00bb3 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2108,6 +2108,8 @@
 
         mWVMExtractor = new WVMExtractor(dataSource);
         mWVMExtractor->setAdaptiveStreamingMode(true);
+        if (mUIDValid)
+            mWVMExtractor->setUID(mUID);
         extractor = mWVMExtractor;
     } else {
         extractor = MediaExtractor::Create(
diff --git a/media/libstagefright/WVMExtractor.cpp b/media/libstagefright/WVMExtractor.cpp
index c7ad513..dac8106 100644
--- a/media/libstagefright/WVMExtractor.cpp
+++ b/media/libstagefright/WVMExtractor.cpp
@@ -123,6 +123,12 @@
     }
 }
 
+void WVMExtractor::setUID(uid_t uid) {
+    if (mImpl != NULL) {
+        mImpl->setUID(uid);
+    }
+}
+
 bool SniffWVM(
     const sp<DataSource> &source, String8 *mimeType, float *confidence,
         sp<AMessage> *) {
diff --git a/media/libstagefright/codecs/aacenc/src/adj_thr.c b/media/libstagefright/codecs/aacenc/src/adj_thr.c
index 373b063..07b33b7 100644
--- a/media/libstagefright/codecs/aacenc/src/adj_thr.c
+++ b/media/libstagefright/codecs/aacenc/src/adj_thr.c
@@ -438,7 +438,7 @@
 	  for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
         Word32 redThrExp = thrExp[ch][sfbGrp+sfb] + redVal;
 
-        if (((*pahFlag < AH_ACTIVE) || (deltaPe > 0)) && (redThrExp > 0) ) {
+        if (((*pahFlag < AH_ACTIVE) || (deltaPe > 0)) && (redThrExp > 0) && (redThrExp >= *psfbNActiveLines)) {
 
           *psfbPeFactors = (*psfbNActiveLines) * (0x7fffffff / redThrExp);
           normFactor = L_add(normFactor, *psfbPeFactors);
@@ -466,7 +466,7 @@
         deltaSfbPe = *psfbPeFactors * deltaPe;
 
 		/* thr3(n) = thr2(n)*2^deltaSfbPe/b(n) */
-        if (*psfbNActiveLines > 0) {
+        if (*psfbNActiveLines > 0 && (normFactor* (*psfbNActiveLines)) != 0) {
           /* new threshold */
           Word32 thrFactor;
           sfbEn  = psyOutChan->sfbEnergy[sfbGrp+sfb];
diff --git a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
index c23dce6..f42a27c 100644
--- a/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
+++ b/media/libstagefright/codecs/amrwbenc/inc/basic_op.h
@@ -29,11 +29,7 @@
 #define MIN_16 (Word16)-32768	/* 0x8000 */
 
 
-#ifdef LINUX
-#define  static_vo  static __inline__
-#else
 #define  static_vo  static __inline
-#endif
 
 #define saturate(L_var1) (((L_var1) > 0X00007fffL) ? (MAX_16): (((L_var1) < (Word32) 0xffff8000L) ? (MIN_16): ((L_var1) & 0xffff)))
 
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 9a00186..8b01ac6 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -74,6 +74,7 @@
 
         case kTypeObject:
         case kTypeMessage:
+        case kTypeBuffer:
         {
             if (item->u.refValue != NULL) {
                 item->u.refValue->decStrong(this);
@@ -292,6 +293,7 @@
             }
 
             case kTypeObject:
+            case kTypeBuffer:
             {
                 to->u.refValue = from->u.refValue;
                 to->u.refValue->incStrong(msg.get());
@@ -396,6 +398,10 @@
                 tmp = StringPrintf(
                         "RefBase *%s = %p", item.mName, item.u.refValue);
                 break;
+            case kTypeBuffer:
+                tmp = StringPrintf(
+                        "ABuffer *%s = %p", item.mName, item.u.refValue);
+                break;
             case kTypeMessage:
                 tmp = StringPrintf(
                         "AMessage %s = %s",
diff --git a/media/libstagefright/include/WVMExtractor.h b/media/libstagefright/include/WVMExtractor.h
index 9f763f9..3c3ca89 100644
--- a/media/libstagefright/include/WVMExtractor.h
+++ b/media/libstagefright/include/WVMExtractor.h
@@ -34,6 +34,7 @@
 
     virtual int64_t getCachedDurationUs(status_t *finalStatus) = 0;
     virtual void setAdaptiveStreamingMode(bool adaptive) = 0;
+    virtual void setUID(uid_t uid) = 0;
 };
 
 class WVMExtractor : public MediaExtractor {
@@ -60,6 +61,8 @@
     // is used.
     void setAdaptiveStreamingMode(bool adaptive);
 
+    void setUID(uid_t uid);
+
     static bool getVendorLibHandle();
 
 protected:
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index fd7418c..37f15e2 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1621,7 +1621,7 @@
         uint32_t strategy = AudioSystem::getStrategyForStream(streamType);
         for (size_t i = 0; i < mTracks.size(); ++i) {
             sp<Track> t = mTracks[i];
-            if (t != 0) {
+            if (t != 0 && !t->isOutputTrack()) {
                 uint32_t actual = AudioSystem::getStrategyForStream(t->streamType());
                 if (sessionId == t->sessionId() && strategy != actual) {
                     ALOGE("createTrack_l() mismatched strategy; expected %u but found %u",
@@ -5192,8 +5192,8 @@
                     reqFormat == mInput->stream->common.get_format(&mInput->stream->common) &&
                     reqFormat == AUDIO_FORMAT_PCM_16_BIT &&
                     ((int)mInput->stream->common.get_sample_rate(&mInput->stream->common) <= (2 * reqSamplingRate)) &&
-                    (popcount(mInput->stream->common.get_channels(&mInput->stream->common)) < 3) &&
-                    (reqChannelCount < 3)) {
+                    popcount(mInput->stream->common.get_channels(&mInput->stream->common)) <= FCC_2 &&
+                    (reqChannelCount <= FCC_2)) {
                     status = NO_ERROR;
                 }
                 if (status == NO_ERROR) {
@@ -5270,7 +5270,7 @@
     mFrameCount = mInputBytes / mFrameSize;
     mRsmpInBuffer = new int16_t[mFrameCount * mChannelCount];
 
-    if (mSampleRate != mReqSampleRate && mChannelCount < 3 && mReqChannelCount < 3)
+    if (mSampleRate != mReqSampleRate && mChannelCount <= FCC_2 && mReqChannelCount <= FCC_2)
     {
         int channelCount;
          // optmization: if mono to mono, use the resampler in stereo to stereo mode to avoid
@@ -5559,7 +5559,7 @@
     if (inStream == NULL && status == BAD_VALUE &&
         reqFormat == format && format == AUDIO_FORMAT_PCM_16_BIT &&
         (samplingRate <= 2 * reqSamplingRate) &&
-        (popcount(channels) < 3) && (popcount(reqChannels) < 3)) {
+        (popcount(channels) <= FCC_2) && (popcount(reqChannels) <= FCC_2)) {
         ALOGV("openInput() reopening with proposed sampling rate and channels");
         status = inHwDev->open_input_stream(inHwDev, *pDevices, &format,
                                             &channels, &samplingRate,
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 2e259c0..d9f2972 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -58,6 +58,15 @@
 
 // ----------------------------------------------------------------------------
 
+// AudioFlinger has a hard-coded upper limit of 2 channels for capture and playback.
+// There is support for > 2 channel tracks down-mixed to 2 channel output via a down-mix effect.
+// Adding full support for > 2 channel capture or playback would require more than simply changing
+// this #define.  There is an independent hard-coded upper limit in AudioMixer;
+// removing that AudioMixer limit would be necessary but insufficient to support > 2 channels.
+// The macro FCC_2 highlights some (but not all) places where there is are 2-channel assumptions.
+// Search also for "2", "left", "right", "[0]", "[1]", ">> 16", "<< 16", etc.
+#define FCC_2 2     // FCC_2 = Fixed Channel Count 2
+
 static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3);
 
 class AudioFlinger :
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 753b1d2..d57326b 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -298,8 +298,7 @@
     ssize_t idx = mInputs.indexOfKey(input);
     InputDesc *inputDesc;
     if (idx < 0) {
-        inputDesc = new InputDesc();
-        inputDesc->mSessionId = audioSession;
+        inputDesc = new InputDesc(audioSession);
         mInputs.add(input, inputDesc);
     } else {
         inputDesc = mInputs.valueAt(idx);
@@ -358,7 +357,6 @@
     }
     InputDesc *inputDesc = mInputs.valueAt(index);
     setPreProcessorEnabled(inputDesc, false);
-    inputDesc->mEffects.clear();
     delete inputDesc;
     mInputs.removeItemsAt(index);
 }
@@ -432,10 +430,12 @@
     return mpAudioPolicy->get_strategy_for_stream(mpAudioPolicy, stream);
 }
 
-uint32_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
+//audio policy: use audio_device_t appropriately
+
+audio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stream)
 {
     if (mpAudioPolicy == NULL) {
-        return 0;
+        return (audio_devices_t)0;
     }
     return mpAudioPolicy->get_devices_for_stream(mpAudioPolicy, stream);
 }
@@ -600,9 +600,9 @@
     return NO_ERROR;
 }
 
-void AudioPolicyService::setPreProcessorEnabled(InputDesc *inputDesc, bool enabled)
+void AudioPolicyService::setPreProcessorEnabled(const InputDesc *inputDesc, bool enabled)
 {
-    Vector<sp<AudioEffect> > fxVector = inputDesc->mEffects;
+    const Vector<sp<AudioEffect> > &fxVector = inputDesc->mEffects;
     for (size_t i = 0; i < fxVector.size(); i++) {
         fxVector.itemAt(i)->setEnabled(enabled);
     }
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index 962c917..7119b90 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -95,7 +95,7 @@
                                           audio_devices_t device);
 
     virtual uint32_t getStrategyForStream(audio_stream_type_t stream);
-    virtual uint32_t getDevicesForStream(audio_stream_type_t stream);
+    virtual audio_devices_t getDevicesForStream(audio_stream_type_t stream);
 
     virtual audio_io_handle_t getOutputForEffect(effect_descriptor_t *desc);
     virtual status_t registerEffect(effect_descriptor_t *desc,
@@ -279,15 +279,15 @@
 
     class InputDesc {
     public:
-        InputDesc() {}
-        virtual ~InputDesc() {}
-        int mSessionId;
+        InputDesc(int session) : mSessionId(session) {}
+        /*virtual*/ ~InputDesc() {}
+        const int mSessionId;
         Vector< sp<AudioEffect> >mEffects;
     };
 
     static const char * const kInputSourceNames[AUDIO_SOURCE_CNT -1];
 
-    void setPreProcessorEnabled(InputDesc *inputDesc, bool enabled);
+    void setPreProcessorEnabled(const InputDesc *inputDesc, bool enabled);
     status_t loadPreProcessorConfig(const char *path);
     status_t loadEffects(cnode *root, Vector <EffectDesc *>& effects);
     EffectDesc *loadEffect(cnode *root);