Merge "Aaudio: Implement app shareable flag instead of -size hack"
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index e3da259..a721b65 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -18,6 +18,8 @@
 #define LOG_TAG "FLACExtractor"
 #include <utils/Log.h>
 
+#include <stdint.h>
+
 #include "FLACExtractor.h"
 // libFLAC parser
 #include "FLAC/stream_decoder.h"
@@ -124,7 +126,7 @@
     // media buffers
     size_t mMaxBufferSize;
     MediaBufferGroup *mGroup;
-    void (*mCopy)(short *dst, const int * src[kMaxChannels], unsigned nSamples, unsigned nChannels);
+    void (*mCopy)(int16_t *dst, const int * src[kMaxChannels], unsigned nSamples, unsigned nChannels);
 
     // handle to underlying libFLAC parser
     FLAC__StreamDecoder *mDecoder;
@@ -383,7 +385,7 @@
 // These are candidates for optimization if needed.
 
 static void copyMono8(
-        short *dst,
+        int16_t *dst,
         const int * src[FLACParser::kMaxChannels],
         unsigned nSamples,
         unsigned /* nChannels */) {
@@ -393,7 +395,7 @@
 }
 
 static void copyStereo8(
-        short *dst,
+        int16_t *dst,
         const int * src[FLACParser::kMaxChannels],
         unsigned nSamples,
         unsigned /* nChannels */) {
@@ -403,7 +405,7 @@
     }
 }
 
-static void copyMultiCh8(short *dst, const int * src[FLACParser::kMaxChannels], unsigned nSamples, unsigned nChannels)
+static void copyMultiCh8(int16_t *dst, const int * src[FLACParser::kMaxChannels], unsigned nSamples, unsigned nChannels)
 {
     for (unsigned i = 0; i < nSamples; ++i) {
         for (unsigned c = 0; c < nChannels; ++c) {
@@ -413,7 +415,7 @@
 }
 
 static void copyMono16(
-        short *dst,
+        int16_t *dst,
         const int * src[FLACParser::kMaxChannels],
         unsigned nSamples,
         unsigned /* nChannels */) {
@@ -423,7 +425,7 @@
 }
 
 static void copyStereo16(
-        short *dst,
+        int16_t *dst,
         const int * src[FLACParser::kMaxChannels],
         unsigned nSamples,
         unsigned /* nChannels */) {
@@ -433,7 +435,7 @@
     }
 }
 
-static void copyMultiCh16(short *dst, const int * src[FLACParser::kMaxChannels], unsigned nSamples, unsigned nChannels)
+static void copyMultiCh16(int16_t *dst, const int * src[FLACParser::kMaxChannels], unsigned nSamples, unsigned nChannels)
 {
     for (unsigned i = 0; i < nSamples; ++i) {
         for (unsigned c = 0; c < nChannels; ++c) {
@@ -445,7 +447,7 @@
 // 24-bit versions should do dithering or noise-shaping, here or in AudioFlinger
 
 static void copyMono24(
-        short *dst,
+        int16_t *dst,
         const int * src[FLACParser::kMaxChannels],
         unsigned nSamples,
         unsigned /* nChannels */) {
@@ -455,7 +457,7 @@
 }
 
 static void copyStereo24(
-        short *dst,
+        int16_t *dst,
         const int * src[FLACParser::kMaxChannels],
         unsigned nSamples,
         unsigned /* nChannels */) {
@@ -465,7 +467,7 @@
     }
 }
 
-static void copyMultiCh24(short *dst, const int * src[FLACParser::kMaxChannels], unsigned nSamples, unsigned nChannels)
+static void copyMultiCh24(int16_t *dst, const int * src[FLACParser::kMaxChannels], unsigned nSamples, unsigned nChannels)
 {
     for (unsigned i = 0; i < nSamples; ++i) {
         for (unsigned c = 0; c < nChannels; ++c) {
@@ -475,7 +477,7 @@
 }
 
 static void copyTrespass(
-        short * /* dst */,
+        int16_t * /* dst */,
         const int *[FLACParser::kMaxChannels] /* src */,
         unsigned /* nSamples */,
         unsigned /* nChannels */) {
@@ -592,7 +594,7 @@
         static const struct {
             unsigned mChannels;
             unsigned mBitsPerSample;
-            void (*mCopy)(short *dst, const int * src[kMaxChannels], unsigned nSamples, unsigned nChannels);
+            void (*mCopy)(int16_t *dst, const int * src[kMaxChannels], unsigned nSamples, unsigned nChannels);
         } table[] = {
             { 1,  8, copyMono8    },
             { 2,  8, copyStereo8  },
@@ -635,7 +637,7 @@
 {
     CHECK(mGroup == NULL);
     mGroup = new MediaBufferGroup;
-    mMaxBufferSize = getMaxBlockSize() * getChannels() * sizeof(short);
+    mMaxBufferSize = getMaxBlockSize() * getChannels() * sizeof(int16_t);
     mGroup->add_buffer(MediaBufferBase::Create(mMaxBufferSize));
 }
 
@@ -688,9 +690,9 @@
     if (err != OK) {
         return NULL;
     }
-    size_t bufferSize = blocksize * getChannels() * sizeof(short);
+    size_t bufferSize = blocksize * getChannels() * sizeof(int16_t);
     CHECK(bufferSize <= mMaxBufferSize);
-    short *data = (short *) buffer->data();
+    int16_t *data = (int16_t *) buffer->data();
     buffer->set_range(0, bufferSize);
     // copy PCM from FLAC write buffer to our media buffer, with interleaving
     (*mCopy)(data, mWriteBuffer, blocksize, getChannels());
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 7b3b81d..5331ba8 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -66,6 +66,8 @@
     kMaxAtomSize = 64 * 1024 * 1024,
 };
 
+static const size_t  kMaxPcmFrameSize = 8192;
+
 class MPEG4Source : public MediaTrack {
 public:
     // Caller retains ownership of both "dataSource" and "sampleTable".
@@ -125,6 +127,7 @@
 
     bool mIsAVC;
     bool mIsHEVC;
+    bool mIsPcm;
     size_t mNALLengthSize;
 
     bool mStarted;
@@ -324,6 +327,11 @@
         case FOURCC('h', 'v', 'c', '1'):
         case FOURCC('h', 'e', 'v', '1'):
             return MEDIA_MIMETYPE_VIDEO_HEVC;
+
+        case FOURCC('t', 'w', 'o', 's'):
+        case FOURCC('s', 'o', 'w', 't'):
+            return MEDIA_MIMETYPE_AUDIO_RAW;
+
         default:
             ALOGW("Unknown fourcc: %c%c%c%c",
                    (fourcc >> 24) & 0xff,
@@ -467,8 +475,15 @@
             if (__builtin_mul_overflow(media_time, samplerate, &delay) ||
                     __builtin_add_overflow(delay, halfscale, &delay) ||
                     (delay /= mHeaderTimescale, false) ||
-                    delay > INT32_MAX ||
-                    delay < INT32_MIN) {
+                    /* the calculated delay should be small, but some apps
+                     * appear to write a bogus edit list that causes a really
+                     * large delay, resulting in playback problems.
+                     * Ignore such edit lists.
+                     * (4096 is enough to drop 4 full samples)
+                     */
+                    delay > 4096 ||
+                    delay < 0) {
+                ALOGW("ignoring edit list with bogus values");
                 return;
             }
             ALOGV("delay = %" PRId64, delay);
@@ -1473,6 +1488,8 @@
         case FOURCC('e', 'n', 'c', 'a'):
         case FOURCC('s', 'a', 'm', 'r'):
         case FOURCC('s', 'a', 'w', 'b'):
+        case FOURCC('t', 'w', 'o', 's'):
+        case FOURCC('s', 'o', 'w', 't'):
         {
             if (mIsQT && chunk_type == FOURCC('m', 'p', '4', 'a')
                     && depth >= 1 && mPath[depth - 1] == FOURCC('w', 'a', 'v', 'e')) {
@@ -1542,6 +1559,13 @@
                 // if the chunk type is enca, we'll get the type from the frma box later
                 mLastTrack->meta.setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
                 AdjustChannelsAndRate(chunk_type, &num_channels, &sample_rate);
+
+                if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_RAW, FourCC2MIME(chunk_type))) {
+                    mLastTrack->meta.setInt32(kKeyBitsPerSample, sample_size);
+                    if (chunk_type == FOURCC('t', 'w', 'o', 's')) {
+                        mLastTrack->meta.setInt32(kKeyPcmBigEndian, 1);
+                    }
+                }
             }
             ALOGV("*** coding='%s' %d channels, size %d, rate %d\n",
                    chunk, num_channels, sample_size, sample_rate);
@@ -3857,6 +3881,7 @@
       mCurrentSampleInfoOffsets(NULL),
       mIsAVC(false),
       mIsHEVC(false),
+      mIsPcm(false),
       mNALLengthSize(0),
       mStarted(false),
       mGroup(NULL),
@@ -3918,6 +3943,27 @@
         mNALLengthSize = 1 + (ptr[14 + 7] & 3);
     }
 
+    mIsPcm = !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW);
+
+    if (mIsPcm) {
+        int32_t numChannels = 0;
+        int32_t bitsPerSample = 0;
+        CHECK(mFormat.findInt32(kKeyBitsPerSample, &bitsPerSample));
+        CHECK(mFormat.findInt32(kKeyChannelCount, &numChannels));
+
+        int32_t bytesPerSample = bitsPerSample >> 3;
+        int32_t pcmSampleSize = bytesPerSample * numChannels;
+
+        size_t maxSampleSize;
+        status_t err = mSampleTable->getMaxSampleSize(&maxSampleSize);
+        if (err != OK || maxSampleSize != static_cast<size_t>(pcmSampleSize) || bitsPerSample != 16) {
+            // Not supported
+            mIsPcm = false;
+        } else {
+            mFormat.setInt32(kKeyMaxInputSize, pcmSampleSize * kMaxPcmFrameSize);
+        }
+    }
+
     CHECK(format.findInt32(kKeyTrackID, &mTrackId));
 
 }
@@ -4832,34 +4878,78 @@
 
     if ((!mIsAVC && !mIsHEVC) || mWantsNALFragments) {
         if (newBuffer) {
-            ssize_t num_bytes_read =
-                mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
+            if (mIsPcm) {
+                // The twos' PCM block reader assumes that all samples has the same size.
 
-            if (num_bytes_read < (ssize_t)size) {
-                mBuffer->release();
-                mBuffer = NULL;
+                uint32_t samplesToRead = mSampleTable->getLastSampleIndexInChunk()
+                                                      - mCurrentSampleIndex + 1;
+                if (samplesToRead > kMaxPcmFrameSize) {
+                    samplesToRead = kMaxPcmFrameSize;
+                }
 
-                return ERROR_IO;
-            }
+                ALOGV("Reading %d PCM frames of size %zu at index %d to stop of chunk at %d",
+                      samplesToRead, size, mCurrentSampleIndex,
+                      mSampleTable->getLastSampleIndexInChunk());
 
-            CHECK(mBuffer != NULL);
-            mBuffer->set_range(0, size);
-            mBuffer->meta_data().clear();
-            mBuffer->meta_data().setInt64(
-                    kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
-            mBuffer->meta_data().setInt64(
-                    kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
+                size_t totalSize = samplesToRead * size;
+                uint8_t* buf = (uint8_t *)mBuffer->data();
+                ssize_t bytesRead = mDataSource->readAt(offset, buf, totalSize);
+                if (bytesRead < (ssize_t)totalSize) {
+                    mBuffer->release();
+                    mBuffer = NULL;
 
-            if (targetSampleTimeUs >= 0) {
-                mBuffer->meta_data().setInt64(
-                        kKeyTargetTime, targetSampleTimeUs);
-            }
+                    return ERROR_IO;
+                }
 
-            if (isSyncSample) {
+                mBuffer->meta_data().clear();
+                mBuffer->meta_data().setInt64(kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
                 mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
-            }
 
-            ++mCurrentSampleIndex;
+                int32_t byteOrder;
+                mFormat.findInt32(kKeyPcmBigEndian, &byteOrder);
+
+                if (byteOrder == 1) {
+                    // Big-endian -> little-endian
+                    uint16_t *dstData = (uint16_t *)buf;
+                    uint16_t *srcData = (uint16_t *)buf;
+
+                    for (size_t j = 0; j < bytesRead / sizeof(uint16_t); j++) {
+                         dstData[j] = ntohs(srcData[j]);
+                    }
+                }
+
+                mCurrentSampleIndex += samplesToRead;
+                mBuffer->set_range(0, totalSize);
+            } else {
+                ssize_t num_bytes_read =
+                    mDataSource->readAt(offset, (uint8_t *)mBuffer->data(), size);
+
+                if (num_bytes_read < (ssize_t)size) {
+                    mBuffer->release();
+                    mBuffer = NULL;
+
+                    return ERROR_IO;
+                }
+
+                CHECK(mBuffer != NULL);
+                mBuffer->set_range(0, size);
+                mBuffer->meta_data().clear();
+                mBuffer->meta_data().setInt64(
+                        kKeyTime, ((int64_t)cts * 1000000) / mTimescale);
+                mBuffer->meta_data().setInt64(
+                        kKeyDuration, ((int64_t)stts * 1000000) / mTimescale);
+
+                if (targetSampleTimeUs >= 0) {
+                    mBuffer->meta_data().setInt64(
+                            kKeyTargetTime, targetSampleTimeUs);
+                }
+
+                if (isSyncSample) {
+                    mBuffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+                }
+
+                ++mCurrentSampleIndex;
+            }
         }
 
         if (!mIsAVC && !mIsHEVC) {
diff --git a/media/extractors/mp4/SampleIterator.h b/media/extractors/mp4/SampleIterator.h
index 6a3fd3b..6e4f60e 100644
--- a/media/extractors/mp4/SampleIterator.h
+++ b/media/extractors/mp4/SampleIterator.h
@@ -36,6 +36,11 @@
     uint32_t getSampleTime() const { return mCurrentSampleTime; }
     uint32_t getSampleDuration() const { return mCurrentSampleDuration; }
 
+    uint32_t getLastSampleIndexInChunk() const {
+        return mCurrentSampleIndex + mSamplesPerChunk -
+                ((mCurrentSampleIndex - mFirstChunkSampleIndex) % mSamplesPerChunk) - 1;
+    }
+
     status_t getSampleSizeDirect(
             uint32_t sampleIndex, size_t *size);
 
diff --git a/media/extractors/mp4/SampleTable.cpp b/media/extractors/mp4/SampleTable.cpp
index 81c353e..28fe717 100644
--- a/media/extractors/mp4/SampleTable.cpp
+++ b/media/extractors/mp4/SampleTable.cpp
@@ -946,6 +946,11 @@
             sampleIndex, sampleSize);
 }
 
+uint32_t SampleTable::getLastSampleIndexInChunk() {
+    Mutex::Autolock autoLock(mLock);
+    return mSampleIterator->getLastSampleIndexInChunk();
+}
+
 status_t SampleTable::getMetaDataForSample(
         uint32_t sampleIndex,
         off64_t *offset,
diff --git a/media/extractors/mp4/SampleTable.h b/media/extractors/mp4/SampleTable.h
index e4e974b..dd68860 100644
--- a/media/extractors/mp4/SampleTable.h
+++ b/media/extractors/mp4/SampleTable.h
@@ -69,6 +69,9 @@
             bool *isSyncSample = NULL,
             uint32_t *sampleDuration = NULL);
 
+    // call only after getMetaDataForSample has been called successfully.
+    uint32_t getLastSampleIndexInChunk();
+
     enum {
         kFlagBefore,
         kFlagAfter,
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index b1cb0e7..b40f0db 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -52,6 +52,7 @@
                 )
     : mStatus(NO_INIT), mOpPackageName(opPackageName)
 {
+    AutoMutex lock(mConstructLock);
     mStatus = set(type, uuid, priority, cbf, user, sessionId, io);
 }
 
@@ -85,6 +86,7 @@
         }
     }
 
+    AutoMutex lock(mConstructLock);
     mStatus = set(pType, pUuid, priority, cbf, user, sessionId, io);
 }
 
diff --git a/media/libaudioclient/include/media/AudioEffect.h b/media/libaudioclient/include/media/AudioEffect.h
index bfc068b..324bcb9 100644
--- a/media/libaudioclient/include/media/AudioEffect.h
+++ b/media/libaudioclient/include/media/AudioEffect.h
@@ -414,6 +414,7 @@
      effect_descriptor_t     mDescriptor;        // effect descriptor
      int32_t                 mId;                // system wide unique effect engine instance ID
      Mutex                   mLock;              // Mutex for mEnabled access
+     Mutex                   mConstructLock;     // Mutex for integrality construction
 
      String16                mOpPackageName;     // The package name used for app op checks.
 
@@ -440,12 +441,22 @@
         virtual void controlStatusChanged(bool controlGranted) {
             sp<AudioEffect> effect = mEffect.promote();
             if (effect != 0) {
+                {
+                    // Got the mConstructLock means the construction of AudioEffect
+                    // has finished, we should release the mConstructLock immediately.
+                    AutoMutex lock(effect->mConstructLock);
+                }
                 effect->controlStatusChanged(controlGranted);
             }
         }
         virtual void enableStatusChanged(bool enabled) {
             sp<AudioEffect> effect = mEffect.promote();
             if (effect != 0) {
+                {
+                    // Got the mConstructLock means the construction of AudioEffect
+                    // has finished, we should release the mConstructLock immediately.
+                    AutoMutex lock(effect->mConstructLock);
+                }
                 effect->enableStatusChanged(enabled);
             }
         }
@@ -456,6 +467,11 @@
                                      void *pReplyData) {
             sp<AudioEffect> effect = mEffect.promote();
             if (effect != 0) {
+                {
+                    // Got the mConstructLock means the construction of AudioEffect
+                    // has finished, we should release the mConstructLock immediately.
+                    AutoMutex lock(effect->mConstructLock);
+                }
                 effect->commandExecuted(
                     cmdCode, cmdSize, pCmdData, replySize, pReplyData);
             }
@@ -465,6 +481,11 @@
         virtual void binderDied(const wp<IBinder>& /*who*/) {
             sp<AudioEffect> effect = mEffect.promote();
             if (effect != 0) {
+                {
+                    // Got the mConstructLock means the construction of AudioEffect
+                    // has finished, we should release the mConstructLock immediately.
+                    AutoMutex lock(effect->mConstructLock);
+                }
                 effect->binderDied();
             }
         }
diff --git a/media/libeffects/config/include/media/EffectsConfig.h b/media/libeffects/config/include/media/EffectsConfig.h
index 55b946f..fa0415b 100644
--- a/media/libeffects/config/include/media/EffectsConfig.h
+++ b/media/libeffects/config/include/media/EffectsConfig.h
@@ -96,7 +96,7 @@
     /** Parsed config, nullptr if the xml lib could not load the file */
     std::unique_ptr<Config> parsedConfig;
     size_t nbSkippedElement; //< Number of skipped invalid library, effect or processing chain
-    const char* configPath; //< Path to the loaded configuration
+    const std::string configPath; //< Path to the loaded configuration
 };
 
 /** Parses the provided effect configuration.
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index d79501f..351b1ee 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -250,14 +250,14 @@
     return true;
 }
 
-/** Internal version of the public parse(const char* path) with precondition `path != nullptr`. */
-ParsingResult parseWithPath(const char* path) {
+/** Internal version of the public parse(const char* path) where path always exist. */
+ParsingResult parseWithPath(std::string&& path) {
     XMLDocument doc;
-    doc.LoadFile(path);
+    doc.LoadFile(path.c_str());
     if (doc.Error()) {
-        ALOGE("Failed to parse %s: Tinyxml2 error (%d): %s", path,
+        ALOGE("Failed to parse %s: Tinyxml2 error (%d): %s", path.c_str(),
               doc.ErrorID(), doc.ErrorStr());
-        return {nullptr, 0, path};
+        return {nullptr, 0, std::move(path)};
     }
 
     auto config = std::make_unique<Config>();
@@ -295,7 +295,7 @@
             }
         }
     }
-    return {std::move(config), nbSkippedElements, path};
+    return {std::move(config), nbSkippedElements, std::move(path)};
 }
 
 }; // namespace
@@ -310,14 +310,14 @@
         if (access(defaultPath.c_str(), R_OK) != 0) {
             continue;
         }
-        auto result = parseWithPath(defaultPath.c_str());
+        auto result = parseWithPath(std::move(defaultPath));
         if (result.parsedConfig != nullptr) {
             return result;
         }
     }
 
     ALOGE("Could not parse effect configuration in any of the default locations.");
-    return {nullptr, 0, nullptr};
+    return {nullptr, 0, ""};
 }
 
 } // namespace effectsConfig
diff --git a/media/libeffects/factory/EffectsXmlConfigLoader.cpp b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
index 7a7d431..052a88b 100644
--- a/media/libeffects/factory/EffectsXmlConfigLoader.cpp
+++ b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
@@ -327,7 +327,8 @@
                                            &gSkippedEffects, &gSubEffectList);
 
     ALOGE_IF(result.nbSkippedElement != 0, "%zu errors during loading of configuration: %s",
-             result.nbSkippedElement, result.configPath ?: "No config file found");
+             result.nbSkippedElement,
+             result.configPath.empty() ? "No config file found" : result.configPath.c_str());
 
     return result.nbSkippedElement;
 }
diff --git a/media/libmediaextractor/MediaBuffer.cpp b/media/libmediaextractor/MediaBuffer.cpp
index 39f8d6e..d197b3f 100644
--- a/media/libmediaextractor/MediaBuffer.cpp
+++ b/media/libmediaextractor/MediaBuffer.cpp
@@ -39,7 +39,7 @@
       mRangeOffset(0),
       mRangeLength(size),
       mOwnsData(false),
-      mMetaData(new MetaData),
+      mMetaData(new MetaDataBase),
       mOriginal(NULL) {
 }
 
@@ -51,7 +51,7 @@
       mRangeOffset(0),
       mRangeLength(size),
       mOwnsData(true),
-      mMetaData(new MetaData),
+      mMetaData(new MetaDataBase),
       mOriginal(NULL) {
     if (size < kSharedMemThreshold
             || std::atomic_load_explicit(&mUseSharedMemory, std::memory_order_seq_cst) == 0) {
@@ -84,7 +84,7 @@
       mRangeLength(mSize),
       mBuffer(buffer),
       mOwnsData(false),
-      mMetaData(new MetaData),
+      mMetaData(new MetaDataBase),
       mOriginal(NULL) {
 }
 
@@ -96,7 +96,7 @@
         return;
     }
 
-    int prevCount = __sync_fetch_and_sub(&mRefCount, 1);
+    int prevCount = mRefCount.fetch_sub(1);
     if (prevCount == 1) {
         if (mObserver == NULL) {
             delete this;
@@ -110,13 +110,13 @@
 
 void MediaBuffer::claim() {
     CHECK(mObserver != NULL);
-    CHECK_EQ(mRefCount, 1);
+    CHECK_EQ(mRefCount.load(std::memory_order_relaxed), 1);
 
-    mRefCount = 0;
+    mRefCount.store(0, std::memory_order_relaxed);
 }
 
 void MediaBuffer::add_ref() {
-    (void) __sync_fetch_and_add(&mRefCount, 1);
+    (void) mRefCount.fetch_add(1);
 }
 
 void *MediaBuffer::data() const {
diff --git a/media/libmediaextractor/include/media/stagefright/MediaBuffer.h b/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
index f944d51..5a25965 100644
--- a/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
+++ b/media/libmediaextractor/include/media/stagefright/MediaBuffer.h
@@ -86,12 +86,14 @@
     virtual MediaBufferBase *clone();
 
     // sum of localRefcount() and remoteRefcount()
+    // Result should be treated as approximate unless the result precludes concurrent accesses.
     virtual int refcount() const {
         return localRefcount() + remoteRefcount();
     }
 
+    // Result should be treated as approximate unless the result precludes concurrent accesses.
     virtual int localRefcount() const {
-        return mRefCount;
+        return mRefCount.load(std::memory_order_relaxed);
     }
 
     virtual int remoteRefcount() const {
@@ -146,7 +148,7 @@
     void claim();
 
     MediaBufferObserver *mObserver;
-    int mRefCount;
+    std::atomic<int> mRefCount;
 
     void *mData;
     size_t mSize, mRangeOffset, mRangeLength;
diff --git a/media/libmediaextractor/include/media/stagefright/MetaDataBase.h b/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
index dfe34e8..9d35568 100644
--- a/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
+++ b/media/libmediaextractor/include/media/stagefright/MetaDataBase.h
@@ -53,6 +53,7 @@
     kKeyFrameRate         = 'frmR',  // int32_t (video frame rate fps)
     kKeyBitRate           = 'brte',  // int32_t (bps)
     kKeyMaxBitRate        = 'mxBr',  // int32_t (bps)
+    kKeyBitsPerSample     = 'bits',  // int32_t (bits per sample)
     kKeyStreamHeader      = 'stHd',  // raw data
     kKeyESDS              = 'esds',  // raw data
     kKeyAACProfile        = 'aacp',  // int32_t
@@ -225,6 +226,8 @@
     kKeyExifOffset       = 'exof', // int64_t, Exif data offset
     kKeyExifSize         = 'exsz', // int64_t, Exif data size
     kKeyIsExif           = 'exif', // bool (int32_t) buffer contains exif data block
+
+    kKeyPcmBigEndian     = 'pcmb', // bool (int32_t)
 };
 
 enum {
diff --git a/media/libstagefright/http/HTTPHelper.cpp b/media/libstagefright/http/HTTPHelper.cpp
index 77845e2..b895f03 100644
--- a/media/libstagefright/http/HTTPHelper.cpp
+++ b/media/libstagefright/http/HTTPHelper.cpp
@@ -42,11 +42,11 @@
             env, env->FindClass("android/media/MediaHTTPService"));
     CHECK(clazz.get() != NULL);
 
-    jmethodID constructID = env->GetMethodID(clazz.get(), "<init>", "()V");
+    jmethodID constructID = env->GetMethodID(clazz.get(), "<init>", "(Ljava/util/List;)V");
     CHECK(constructID != NULL);
 
     ScopedLocalRef<jobject> httpServiceObj(
-            env, env->NewObject(clazz.get(), constructID));
+            env, env->NewObject(clazz.get(), constructID, NULL));
 
     sp<IMediaHTTPService> httpService;
     if (httpServiceObj.get() != NULL) {
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 2047dfd..20c9d37 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -50,6 +50,8 @@
 #define ALOGVV(a...) do { } while(0)
 #endif
 
+#define DEFAULT_OUTPUT_SAMPLE_RATE 48000
+
 namespace android {
 
 // ----------------------------------------------------------------------------
@@ -263,7 +265,9 @@
         }
         break;
     case STOPPING:
-        if (stop_l() == NO_ERROR) {
+        // volume control for offload and direct threads must take effect immediately.
+        if (stop_l() == NO_ERROR
+            && !(isVolumeControl() && isOffloadedOrDirect())) {
             mDisableWaitCnt = mMaxDisableWaitCnt;
         } else {
             mDisableWaitCnt = 1; // will cause immediate transition to IDLE
@@ -547,7 +551,14 @@
 
     mConfig.inputCfg.format = EFFECT_BUFFER_FORMAT;
     mConfig.outputCfg.format = EFFECT_BUFFER_FORMAT;
-    mConfig.inputCfg.samplingRate = thread->sampleRate();
+
+    // Don't use sample rate for thread if effect isn't offloadable.
+    if ((thread->type() == ThreadBase::OFFLOAD) && !isOffloaded()) {
+        mConfig.inputCfg.samplingRate = DEFAULT_OUTPUT_SAMPLE_RATE;
+        ALOGV("Overriding effect input as 48kHz");
+    } else {
+        mConfig.inputCfg.samplingRate = thread->sampleRate();
+    }
     mConfig.outputCfg.samplingRate = mConfig.inputCfg.samplingRate;
     mConfig.inputCfg.bufferProvider.cookie = NULL;
     mConfig.inputCfg.bufferProvider.getBuffer = NULL;
@@ -778,6 +789,16 @@
     }
     status_t cmdStatus = NO_ERROR;
     uint32_t size = sizeof(status_t);
+
+    if (isVolumeControl() && isOffloadedOrDirect()) {
+        sp<EffectChain>chain = mChain.promote();
+        // We have the EffectChain and EffectModule lock, permit a reentrant call to setVolume:
+        // resetVolume_l --> setVolume_l --> EffectModule::setVolume
+        mSetVolumeReentrantTid = gettid();
+        chain->resetVolume_l();
+        mSetVolumeReentrantTid = INVALID_PID;
+    }
+
     status_t status = mEffectInterface->command(EFFECT_CMD_DISABLE,
                                                 0,
                                                 NULL,
@@ -993,6 +1014,16 @@
     }
 }
 
+bool AudioFlinger::EffectModule::isOffloadedOrDirect() const
+{
+    return (mThreadType == ThreadBase::OFFLOAD || mThreadType == ThreadBase::DIRECT);
+}
+
+bool AudioFlinger::EffectModule::isVolumeControlEnabled() const
+{
+    return (isVolumeControl() && (isOffloadedOrDirect() ? isEnabled() : isProcessEnabled()));
+}
+
 void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
     ALOGVV("setInBuffer %p",(&buffer));
 
@@ -1091,7 +1122,7 @@
 
 status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
 {
-    Mutex::Autolock _l(mLock);
+    AutoLockReentrant _l(mLock, mSetVolumeReentrantTid);
     if (mStatus != NO_ERROR) {
         return mStatus;
     }
@@ -1122,6 +1153,18 @@
     return status;
 }
 
+void AudioFlinger::EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
+{
+    sp<ThreadBase> thread = mThread.promote();
+    if (thread != 0 &&
+        (thread->type() == ThreadBase::OFFLOAD || thread->type() == ThreadBase::DIRECT)) {
+        PlaybackThread *t = (PlaybackThread *)thread.get();
+        float vol_l = (float)left / (1 << 24);
+        float vol_r = (float)right / (1 << 24);
+        t->setVolumeForOutput_l(vol_l, vol_r);
+    }
+}
+
 status_t AudioFlinger::EffectModule::setDevice(audio_devices_t device)
 {
     if (device == AUDIO_DEVICE_NONE) {
@@ -2200,8 +2243,7 @@
 
     // first update volume controller
     for (size_t i = size; i > 0; i--) {
-        if (mEffects[i - 1]->isProcessEnabled() &&
-            (mEffects[i - 1]->desc().flags & EFFECT_FLAG_VOLUME_MASK) == EFFECT_FLAG_VOLUME_CTRL) {
+        if (mEffects[i - 1]->isVolumeControlEnabled()) {
             ctrlIdx = i - 1;
             hasControl = true;
             break;
@@ -2247,6 +2289,8 @@
     *left = newLeft;
     *right = newRight;
 
+    setVolumeForOutput_l(*left, *right);
+
     return hasControl;
 }
 
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 2327bb9..e04ee8e 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -85,6 +85,8 @@
     status_t    setEnabled_l(bool enabled);
     bool isEnabled() const;
     bool isProcessEnabled() const;
+    bool isOffloadedOrDirect() const;
+    bool isVolumeControlEnabled() const;
 
     void        setInBuffer(const sp<EffectBufferHalInterface>& buffer);
     int16_t     *inBuffer() const {
@@ -95,7 +97,8 @@
         return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL;
     }
     void        setChain(const wp<EffectChain>& chain) { mChain = chain; }
-    void        setThread(const wp<ThreadBase>& thread) { mThread = thread; }
+    void        setThread(const wp<ThreadBase>& thread)
+                    { mThread = thread; mThreadType = thread.promote()->type(); }
     const wp<ThreadBase>& thread() { return mThread; }
 
     status_t addHandle(EffectHandle *handle);
@@ -128,6 +131,9 @@
                         { return (mDescriptor.flags & EFFECT_FLAG_HW_ACC_MASK) == 0; }
     bool             isProcessImplemented() const
                         { return (mDescriptor.flags & EFFECT_FLAG_NO_PROCESS) == 0; }
+    bool             isVolumeControl() const
+                        { return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK)
+                            == EFFECT_FLAG_VOLUME_CTRL; }
     status_t         setOffloaded(bool offloaded, audio_io_handle_t io);
     bool             isOffloaded() const;
     void             addEffectToHal_l();
@@ -150,6 +156,7 @@
 
 mutable Mutex               mLock;      // mutex for process, commands and handles list protection
     wp<ThreadBase>      mThread;    // parent thread
+    ThreadBase::type_t  mThreadType; // parent thread type
     wp<EffectChain>     mChain;     // parent effect chain
     const int           mId;        // this instance unique ID
     const audio_session_t mSessionId; // audio session ID
@@ -176,6 +183,24 @@
     uint32_t mInChannelCountRequested;
     uint32_t mOutChannelCountRequested;
 #endif
+
+    class AutoLockReentrant {
+    public:
+        AutoLockReentrant(Mutex& mutex, pid_t allowedTid)
+            : mMutex(gettid() == allowedTid ? nullptr : &mutex)
+        {
+            if (mMutex != nullptr) mMutex->lock();
+        }
+        ~AutoLockReentrant() {
+            if (mMutex != nullptr) mMutex->unlock();
+        }
+    private:
+        Mutex * const mMutex;
+    };
+
+    static constexpr pid_t INVALID_PID = (pid_t)-1;
+    // this tid is allowed to call setVolume() without acquiring the mutex.
+    pid_t mSetVolumeReentrantTid = INVALID_PID;
 };
 
 // The EffectHandle class implements the IEffect interface. It provides resources
@@ -403,6 +428,8 @@
 
     void setThread(const sp<ThreadBase>& thread);
 
+    void setVolumeForOutput_l(uint32_t left, uint32_t right);
+
              wp<ThreadBase> mThread;     // parent mixer thread
     mutable  Mutex mLock;        // mutex protecting effect list
              Vector< sp<EffectModule> > mEffects; // list of effect modules
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index dcad866..4ca50d7 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2286,6 +2286,11 @@
     return mStreamTypes[stream].volume;
 }
 
+void AudioFlinger::PlaybackThread::setVolumeForOutput_l(float left, float right) const
+{
+    mOutput->stream->setVolume(left, right);
+}
+
 // addTrack_l() must be called with ThreadBase::mLock held
 status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
 {
@@ -5142,20 +5147,20 @@
             mLeftVolFloat = left;
             mRightVolFloat = right;
 
-            // Convert volumes from float to 8.24
-            uint32_t vl = (uint32_t)(left * (1 << 24));
-            uint32_t vr = (uint32_t)(right * (1 << 24));
-
             // Delegate volume control to effect in track effect chain if needed
             // only one effect chain can be present on DirectOutputThread, so if
             // there is one, the track is connected to it
             if (!mEffectChains.isEmpty()) {
-                mEffectChains[0]->setVolume_l(&vl, &vr);
-                left = (float)vl / (1 << 24);
-                right = (float)vr / (1 << 24);
+                // if effect chain exists, volume is handled by it.
+                // Convert volumes from float to 8.24
+                uint32_t vl = (uint32_t)(left * (1 << 24));
+                uint32_t vr = (uint32_t)(right * (1 << 24));
+                // Direct/Offload effect chains set output volume in setVolume_l().
+                (void)mEffectChains[0]->setVolume_l(&vl, &vr);
+            } else {
+                // otherwise we directly set the volume.
+                setVolumeForOutput_l(left, right);
             }
-            status_t result = mOutput->stream->setVolume(left, right);
-            ALOGE_IF(result != OK, "Error when setting output stream volume: %d", result);
         }
     }
 }
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 28d4482..ea29455 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -712,6 +712,8 @@
     virtual     void        setStreamMute(audio_stream_type_t stream, bool muted);
     virtual     float       streamVolume(audio_stream_type_t stream) const;
 
+                void        setVolumeForOutput_l(float left, float right) const;
+
                 sp<Track>   createTrack_l(
                                 const sp<AudioFlinger::Client>& client,
                                 audio_stream_type_t streamType,