Merge "Get screenrecord to exclude black cutout"
diff --git a/camera/ndk/NdkCameraManager.cpp b/camera/ndk/NdkCameraManager.cpp
index 60b4763..f14a4c9 100644
--- a/camera/ndk/NdkCameraManager.cpp
+++ b/camera/ndk/NdkCameraManager.cpp
@@ -23,6 +23,7 @@
 
 #include <camera/NdkCameraManager.h>
 #include "impl/ACameraManager.h"
+#include "impl/ACameraMetadata.h"
 
 using namespace android;
 
@@ -107,7 +108,14 @@
                 __FUNCTION__, mgr, cameraId, chars);
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
-    return mgr->getCameraCharacteristics(cameraId, chars);
+    sp<ACameraMetadata> spChars;
+    camera_status_t status = mgr->getCameraCharacteristics(cameraId, &spChars);
+    if (status != ACAMERA_OK) {
+        return status;
+    }
+    spChars->incStrong((void*) ACameraManager_getCameraCharacteristics);
+    *chars = spChars.get();
+    return ACAMERA_OK;
 }
 
 EXPORT
diff --git a/camera/ndk/NdkCameraMetadata.cpp b/camera/ndk/NdkCameraMetadata.cpp
index 65de81f..34ec2da 100644
--- a/camera/ndk/NdkCameraMetadata.cpp
+++ b/camera/ndk/NdkCameraMetadata.cpp
@@ -57,13 +57,15 @@
         ALOGE("%s: src is null!", __FUNCTION__);
         return nullptr;
     }
-    return new ACameraMetadata(*src);
+    ACameraMetadata* copy = new ACameraMetadata(*src);
+    copy->incStrong((void*) ACameraMetadata_copy);
+    return copy;
 }
 
 EXPORT
 void ACameraMetadata_free(ACameraMetadata* metadata) {
     ATRACE_CALL();
     if (metadata != nullptr) {
-        delete metadata;
+        metadata->decStrong((void*) ACameraMetadata_free);
     }
 }
diff --git a/camera/ndk/NdkCaptureRequest.cpp b/camera/ndk/NdkCaptureRequest.cpp
index ac1856b..ddb69d7 100644
--- a/camera/ndk/NdkCaptureRequest.cpp
+++ b/camera/ndk/NdkCaptureRequest.cpp
@@ -137,7 +137,7 @@
     if (request == nullptr) {
         return;
     }
-    delete request->settings;
+    request->settings.clear();
     delete request->targets;
     delete request;
     return;
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 907debc..c908323 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -50,11 +50,11 @@
 CameraDevice::CameraDevice(
         const char* id,
         ACameraDevice_StateCallbacks* cb,
-        std::unique_ptr<ACameraMetadata> chars,
+        sp<ACameraMetadata> chars,
         ACameraDevice* wrapper) :
         mCameraId(id),
         mAppCallbacks(*cb),
-        mChars(std::move(chars)),
+        mChars(chars),
         mServiceCallback(new ServiceCallback(this)),
         mWrapper(wrapper),
         mInError(false),
@@ -436,7 +436,7 @@
     if (req == nullptr) {
         return;
     }
-    delete req->settings;
+    req->settings.clear();
     delete req->targets;
     delete req;
 }
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 1369148..7d64081 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -48,7 +48,7 @@
 class CameraDevice final : public RefBase {
   public:
     CameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
-                  std::unique_ptr<ACameraMetadata> chars,
+                  sp<ACameraMetadata> chars,
                   ACameraDevice* wrapper);
     ~CameraDevice();
 
@@ -156,7 +156,7 @@
     mutable Mutex mDeviceLock;
     const String8 mCameraId;                          // Camera ID
     const ACameraDevice_StateCallbacks mAppCallbacks; // Callback to app
-    const std::unique_ptr<ACameraMetadata> mChars;    // Camera characteristics
+    const sp<ACameraMetadata> mChars;                 // Camera characteristics
     const sp<ServiceCallback> mServiceCallback;
     ACameraDevice* mWrapper;
 
@@ -294,8 +294,8 @@
  */
 struct ACameraDevice {
     ACameraDevice(const char* id, ACameraDevice_StateCallbacks* cb,
-                  std::unique_ptr<ACameraMetadata> chars) :
-            mDevice(new CameraDevice(id, cb, std::move(chars), this)) {}
+                  sp<ACameraMetadata> chars) :
+            mDevice(new CameraDevice(id, cb, chars, this)) {}
 
     ~ACameraDevice() {};
 
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index c59d0e7..ee67677 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -402,7 +402,7 @@
 }
 
 camera_status_t ACameraManager::getCameraCharacteristics(
-        const char *cameraIdStr, ACameraMetadata **characteristics) {
+        const char* cameraIdStr, sp<ACameraMetadata>* characteristics) {
     Mutex::Autolock _l(mLock);
 
     sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
@@ -437,18 +437,16 @@
         const char* cameraId,
         ACameraDevice_StateCallbacks* callback,
         /*out*/ACameraDevice** outDevice) {
-    ACameraMetadata* rawChars;
-    camera_status_t ret = getCameraCharacteristics(cameraId, &rawChars);
+    sp<ACameraMetadata> chars;
+    camera_status_t ret = getCameraCharacteristics(cameraId, &chars);
     Mutex::Autolock _l(mLock);
     if (ret != ACAMERA_OK) {
         ALOGE("%s: cannot get camera characteristics for camera %s. err %d",
                 __FUNCTION__, cameraId, ret);
         return ACAMERA_ERROR_INVALID_PARAMETER;
     }
-    std::unique_ptr<ACameraMetadata> chars(rawChars);
-    rawChars = nullptr;
 
-    ACameraDevice* device = new ACameraDevice(cameraId, callback, std::move(chars));
+    ACameraDevice* device = new ACameraDevice(cameraId, callback, chars);
 
     sp<hardware::ICameraService> cs = CameraManagerGlobal::getInstance().getCameraService();
     if (cs == nullptr) {
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index cc42f77..ce65769 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -186,7 +186,7 @@
     static void     deleteCameraIdList(ACameraIdList* cameraIdList);
 
     camera_status_t getCameraCharacteristics(
-            const char *cameraId, ACameraMetadata **characteristics);
+            const char* cameraId, android::sp<ACameraMetadata>* characteristics);
     camera_status_t openCamera(const char* cameraId,
                                ACameraDevice_StateCallbacks* callback,
                                /*out*/ACameraDevice** device);
diff --git a/camera/ndk/impl/ACaptureRequest.h b/camera/ndk/impl/ACaptureRequest.h
index 06b2cc3..b11dafb 100644
--- a/camera/ndk/impl/ACaptureRequest.h
+++ b/camera/ndk/impl/ACaptureRequest.h
@@ -55,7 +55,7 @@
         return ACAMERA_OK;
     }
 
-    ACameraMetadata*      settings;
+    sp<ACameraMetadata>   settings;
     ACameraOutputTargets* targets;
     void*                 context;
 };
diff --git a/include/media/MediaExtractorPluginApi.h b/include/media/MediaExtractorPluginApi.h
new file mode 100644
index 0000000..930b6e2
--- /dev/null
+++ b/include/media/MediaExtractorPluginApi.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_EXTRACTOR_PLUGIN_API_H_
+#define MEDIA_EXTRACTOR_PLUGIN_API_H_
+
+#include <utils/Errors.h> // for status_t
+
+namespace android {
+
+struct MediaTrack;
+class MetaDataBase;
+
+extern "C" {
+
+struct CDataSource {
+    ssize_t (*readAt)(void *handle, off64_t offset, void *data, size_t size);
+    status_t (*getSize)(void *handle, off64_t *size);
+    uint32_t (*flags)(void *handle );
+    bool (*getUri)(void *handle, char *uriString, size_t bufferSize);
+    void *handle;
+};
+
+struct CMediaExtractor {
+    void *data;
+
+    void (*free)(void *data);
+    size_t (*countTracks)(void *data);
+    MediaTrack* (*getTrack)(void *data, size_t index);
+    status_t (*getTrackMetaData)(
+            void *data,
+            MetaDataBase& meta,
+            size_t index, uint32_t flags);
+
+    status_t (*getMetaData)(void *data, MetaDataBase& meta);
+    uint32_t (*flags)(void *data);
+    status_t (*setMediaCas)(void *data, const uint8_t* casToken, size_t size);
+    const char * (*name)(void *data);
+};
+
+typedef CMediaExtractor* (*CreatorFunc)(CDataSource *source, void *meta);
+typedef void (*FreeMetaFunc)(void *meta);
+
+// The sniffer can optionally fill in an opaque object, "meta", that helps
+// the corresponding extractor initialize its state without duplicating
+// effort already exerted by the sniffer. If "freeMeta" is given, it will be
+// called against the opaque object when it is no longer used.
+typedef CreatorFunc (*SnifferFunc)(
+        CDataSource *source, float *confidence,
+        void **meta, FreeMetaFunc *freeMeta);
+
+typedef struct {
+    const uint8_t b[16];
+} media_uuid_t;
+
+typedef struct {
+    // version number of this structure
+    const uint32_t def_version;
+
+    // A unique identifier for this extractor.
+    // See below for a convenience macro to create this from a string.
+    media_uuid_t extractor_uuid;
+
+    // Version number of this extractor. When two extractors with the same
+    // uuid are encountered, the one with the largest version number will
+    // be used.
+    const uint32_t extractor_version;
+
+    // a human readable name
+    const char *extractor_name;
+
+    // the sniffer function
+    const SnifferFunc sniff;
+} ExtractorDef;
+
+const uint32_t EXTRACTORDEF_VERSION = 1;
+
+// each plugin library exports one function of this type
+typedef ExtractorDef (*GetExtractorDef)();
+
+} // extern "C"
+
+}  // namespace android
+
+#endif  // MEDIA_EXTRACTOR_PLUGIN_API_H_
diff --git a/include/media/MediaExtractorPluginHelper.h b/include/media/MediaExtractorPluginHelper.h
new file mode 100644
index 0000000..c817b30
--- /dev/null
+++ b/include/media/MediaExtractorPluginHelper.h
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_EXTRACTOR_PLUGIN_HELPER_H_
+
+#define MEDIA_EXTRACTOR_PLUGIN_HELPER_H_
+
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <vector>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+#include <media/MediaExtractorPluginApi.h>
+
+namespace android {
+
+class DataSourceBase;
+class MetaDataBase;
+struct MediaTrack;
+
+// extractor plugins can derive from this class which looks remarkably
+// like MediaExtractor and can be easily wrapped in the required C API
+class MediaExtractorPluginHelper
+{
+public:
+    virtual ~MediaExtractorPluginHelper() {}
+    virtual size_t countTracks() = 0;
+    virtual MediaTrack *getTrack(size_t index) = 0;
+
+    enum GetTrackMetaDataFlags {
+        kIncludeExtensiveMetaData = 1
+    };
+    virtual status_t getTrackMetaData(
+            MetaDataBase& meta,
+            size_t index, uint32_t flags = 0) = 0;
+
+    // Return container specific meta-data. The default implementation
+    // returns an empty metadata object.
+    virtual status_t getMetaData(MetaDataBase& meta) = 0;
+
+    enum Flags {
+        CAN_SEEK_BACKWARD  = 1,  // the "seek 10secs back button"
+        CAN_SEEK_FORWARD   = 2,  // the "seek 10secs forward button"
+        CAN_PAUSE          = 4,
+        CAN_SEEK           = 8,  // the "seek bar"
+    };
+
+    // If subclasses do _not_ override this, the default is
+    // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE
+    virtual uint32_t flags() const {
+        return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK | CAN_PAUSE;
+    };
+
+    virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) {
+        return INVALID_OPERATION;
+    }
+
+    virtual const char * name() { return "<unspecified>"; }
+
+protected:
+    MediaExtractorPluginHelper() {}
+
+private:
+    MediaExtractorPluginHelper(const MediaExtractorPluginHelper &);
+    MediaExtractorPluginHelper &operator=(const MediaExtractorPluginHelper &);
+};
+
+inline CMediaExtractor *wrap(MediaExtractorPluginHelper *extractor) {
+    CMediaExtractor *wrapper = (CMediaExtractor*) malloc(sizeof(CMediaExtractor));
+    wrapper->data = extractor;
+    wrapper->free = [](void *data) -> void {
+        delete (MediaExtractorPluginHelper*)(data);
+    };
+    wrapper->countTracks = [](void *data) -> size_t {
+        return ((MediaExtractorPluginHelper*)data)->countTracks();
+    };
+    wrapper->getTrack = [](void *data, size_t index) -> MediaTrack* {
+        return ((MediaExtractorPluginHelper*)data)->getTrack(index);
+    };
+    wrapper->getTrackMetaData = [](
+            void *data,
+            MetaDataBase& meta,
+            size_t index, uint32_t flags) -> status_t {
+        return ((MediaExtractorPluginHelper*)data)->getTrackMetaData(meta, index, flags);
+    };
+    wrapper->getMetaData = [](
+            void *data,
+            MetaDataBase& meta) -> status_t {
+        return ((MediaExtractorPluginHelper*)data)->getMetaData(meta);
+    };
+    wrapper->flags = [](
+            void *data) -> uint32_t {
+        return ((MediaExtractorPluginHelper*)data)->flags();
+    };
+    wrapper->setMediaCas = [](
+            void *data, const uint8_t *casToken, size_t size) -> status_t {
+        return ((MediaExtractorPluginHelper*)data)->setMediaCas(casToken, size);
+    };
+    wrapper->name = [](
+            void *data) -> const char * {
+        return ((MediaExtractorPluginHelper*)data)->name();
+    };
+    return wrapper;
+}
+
+/* adds some convience methods */
+class DataSourceHelper {
+public:
+    explicit DataSourceHelper(CDataSource *csource) {
+        mSource = csource;
+    }
+
+    explicit DataSourceHelper(DataSourceHelper *source) {
+        mSource = source->mSource;
+    }
+
+    ssize_t readAt(off64_t offset, void *data, size_t size) {
+        return mSource->readAt(mSource->handle, offset, data, size);
+    }
+
+    status_t getSize(off64_t *size) {
+        return mSource->getSize(mSource->handle, size);
+    }
+
+    bool getUri(char *uriString, size_t bufferSize) {
+        return mSource->getUri(mSource->handle, uriString, bufferSize);
+    }
+
+    uint32_t flags() {
+        return mSource->flags(mSource->handle);
+    }
+
+    // Convenience methods:
+    bool getUInt16(off64_t offset, uint16_t *x) {
+        *x = 0;
+
+        uint8_t byte[2];
+        if (readAt(offset, byte, 2) != 2) {
+            return false;
+        }
+
+        *x = (byte[0] << 8) | byte[1];
+
+        return true;
+    }
+
+    // 3 byte int, returned as a 32-bit int
+    bool getUInt24(off64_t offset, uint32_t *x) {
+        *x = 0;
+
+        uint8_t byte[3];
+        if (readAt(offset, byte, 3) != 3) {
+            return false;
+        }
+
+        *x = (byte[0] << 16) | (byte[1] << 8) | byte[2];
+
+        return true;
+    }
+
+    bool getUInt32(off64_t offset, uint32_t *x) {
+        *x = 0;
+
+        uint32_t tmp;
+        if (readAt(offset, &tmp, 4) != 4) {
+            return false;
+        }
+
+        *x = ntohl(tmp);
+
+        return true;
+    }
+
+    bool getUInt64(off64_t offset, uint64_t *x) {
+        *x = 0;
+
+        uint64_t tmp;
+        if (readAt(offset, &tmp, 8) != 8) {
+            return false;
+        }
+
+        *x = ((uint64_t)ntohl(tmp & 0xffffffff) << 32) | ntohl(tmp >> 32);
+
+        return true;
+    }
+
+    // read either int<N> or int<2N> into a uint<2N>_t, size is the int size in bytes.
+    bool getUInt16Var(off64_t offset, uint16_t *x, size_t size) {
+        if (size == 2) {
+            return getUInt16(offset, x);
+        }
+        if (size == 1) {
+            uint8_t tmp;
+            if (readAt(offset, &tmp, 1) == 1) {
+                *x = tmp;
+                return true;
+            }
+        }
+        return false;
+    }
+
+    bool getUInt32Var(off64_t offset, uint32_t *x, size_t size) {
+        if (size == 4) {
+            return getUInt32(offset, x);
+        }
+        if (size == 2) {
+            uint16_t tmp;
+            if (getUInt16(offset, &tmp)) {
+                *x = tmp;
+                return true;
+            }
+        }
+        return false;
+    }
+
+    bool getUInt64Var(off64_t offset, uint64_t *x, size_t size) {
+        if (size == 8) {
+            return getUInt64(offset, x);
+        }
+        if (size == 4) {
+            uint32_t tmp;
+            if (getUInt32(offset, &tmp)) {
+                *x = tmp;
+                return true;
+            }
+        }
+        return false;
+    }
+
+protected:
+    CDataSource *mSource;
+};
+
+
+
+// helpers to create a media_uuid_t from a string literal
+
+// purposely not defined anywhere so that this will fail to link if
+// expressions below are not evaluated at compile time
+int invalid_uuid_string(const char *);
+
+template <typename T, size_t N>
+constexpr uint8_t _digitAt_(const T (&s)[N], const size_t n) {
+    return s[n] >= '0' && s[n] <= '9' ? s[n] - '0'
+            : s[n] >= 'a' && s[n] <= 'f' ? s[n] - 'a' + 10
+                    : s[n] >= 'A' && s[n] <= 'F' ? s[n] - 'A' + 10
+                            : invalid_uuid_string("uuid: bad digits");
+}
+
+template <typename T, size_t N>
+constexpr uint8_t _hexByteAt_(const T (&s)[N], size_t n) {
+    return (_digitAt_(s, n) << 4) + _digitAt_(s, n + 1);
+}
+
+constexpr bool _assertIsDash_(char c) {
+    return c == '-' ? true : invalid_uuid_string("Wrong format");
+}
+
+template <size_t N>
+constexpr media_uuid_t constUUID(const char (&s) [N]) {
+    static_assert(N == 37, "uuid: wrong length");
+    return
+            _assertIsDash_(s[8]),
+            _assertIsDash_(s[13]),
+            _assertIsDash_(s[18]),
+            _assertIsDash_(s[23]),
+            media_uuid_t {{
+                _hexByteAt_(s, 0),
+                _hexByteAt_(s, 2),
+                _hexByteAt_(s, 4),
+                _hexByteAt_(s, 6),
+                _hexByteAt_(s, 9),
+                _hexByteAt_(s, 11),
+                _hexByteAt_(s, 14),
+                _hexByteAt_(s, 16),
+                _hexByteAt_(s, 19),
+                _hexByteAt_(s, 21),
+                _hexByteAt_(s, 24),
+                _hexByteAt_(s, 26),
+                _hexByteAt_(s, 28),
+                _hexByteAt_(s, 30),
+                _hexByteAt_(s, 32),
+                _hexByteAt_(s, 34),
+            }};
+}
+// Convenience macro to create a media_uuid_t from a string literal, which should
+// be formatted as "12345678-1234-1234-1234-123456789abc", as generated by
+// e.g. https://www.uuidgenerator.net/ or the 'uuidgen' linux command.
+// Hex digits may be upper or lower case.
+//
+// The macro call is otherwise equivalent to specifying the structure directly
+// (e.g. UUID("7d613858-5837-4a38-84c5-332d1cddee27") is the same as
+//       {{0x7d, 0x61, 0x38, 0x58, 0x58, 0x37, 0x4a, 0x38,
+//         0x84, 0xc5, 0x33, 0x2d, 0x1c, 0xdd, 0xee, 0x27}})
+
+#define UUID(str) []{ constexpr media_uuid_t uuid = constUUID(str); return uuid; }()
+
+}  // namespace android
+
+#endif  // MEDIA_EXTRACTOR_PLUGIN_HELPER_H_
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index 9fc5a76..955a588 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -19,7 +19,7 @@
 #include <utils/Log.h>
 
 #include "AACExtractor.h"
-#include <media/DataSourceBase.h>
+#include <media/MediaExtractorPluginApi.h>
 #include <media/MediaTrack.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -36,7 +36,7 @@
 class AACSource : public MediaTrack {
 public:
     AACSource(
-            DataSourceBase *source,
+            DataSourceHelper *source,
             MetaDataBase &meta,
             const Vector<uint64_t> &offset_vector,
             int64_t frame_duration_us);
@@ -54,7 +54,7 @@
 
 private:
     static const size_t kMaxFrameSize;
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     MetaDataBase mMeta;
 
     off64_t mOffset;
@@ -92,7 +92,7 @@
 // The returned value is the AAC frame size with the ADTS header length (regardless of
 //     the presence of the CRC).
 // If headerSize is non-NULL, it will be used to return the size of the header of this ADTS frame.
-static size_t getAdtsFrameLength(DataSourceBase *source, off64_t offset, size_t* headerSize) {
+static size_t getAdtsFrameLength(DataSourceHelper *source, off64_t offset, size_t* headerSize) {
 
     const size_t kAdtsHeaderLengthNoCrc = 7;
     const size_t kAdtsHeaderLengthWithCrc = 9;
@@ -133,7 +133,7 @@
 }
 
 AACExtractor::AACExtractor(
-        DataSourceBase *source, off64_t offset)
+        DataSourceHelper *source, off64_t offset)
     : mDataSource(source),
       mInitCheck(NO_INIT),
       mFrameDurationUs(0) {
@@ -219,7 +219,7 @@
 const size_t AACSource::kMaxFrameSize = 8192;
 
 AACSource::AACSource(
-        DataSourceBase *source,
+        DataSourceHelper *source,
         MetaDataBase &meta,
         const Vector<uint64_t> &offset_vector,
         int64_t frame_duration_us)
@@ -323,21 +323,22 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-static MediaExtractor* CreateExtractor(
-        DataSourceBase *source,
+static CMediaExtractor* CreateExtractor(
+        CDataSource *source,
         void *meta) {
     off64_t offset = *static_cast<off64_t*>(meta);
-    return new AACExtractor(source, offset);
+    return wrap(new AACExtractor(new DataSourceHelper(source), offset));
 }
 
-static MediaExtractor::CreatorFunc Sniff(
-        DataSourceBase *source, float *confidence, void **meta,
-        MediaExtractor::FreeMetaFunc *freeMeta) {
+static CreatorFunc Sniff(
+        CDataSource *source, float *confidence, void **meta,
+        FreeMetaFunc *freeMeta) {
     off64_t pos = 0;
 
+    DataSourceHelper helper(source);
     for (;;) {
         uint8_t id3header[10];
-        if (source->readAt(pos, id3header, sizeof(id3header))
+        if (helper.readAt(pos, id3header, sizeof(id3header))
                 < (ssize_t)sizeof(id3header)) {
             return NULL;
         }
@@ -364,7 +365,7 @@
 
     uint8_t header[2];
 
-    if (source->readAt(pos, &header, 2) != 2) {
+    if (helper.readAt(pos, &header, 2) != 2) {
         return NULL;
     }
 
@@ -387,9 +388,9 @@
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
-MediaExtractor::ExtractorDef GETEXTRACTORDEF() {
+ExtractorDef GETEXTRACTORDEF() {
     return {
-        MediaExtractor::EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION,
         UUID("4fd80eae-03d2-4d72-9eb9-48fa6bb54613"),
         1, // version
         "AAC Extractor",
diff --git a/media/extractors/aac/AACExtractor.h b/media/extractors/aac/AACExtractor.h
index 9dadbed..3f20461 100644
--- a/media/extractors/aac/AACExtractor.h
+++ b/media/extractors/aac/AACExtractor.h
@@ -18,7 +18,8 @@
 
 #define AAC_EXTRACTOR_H_
 
-#include <media/MediaExtractor.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MetaDataBase.h>
 
 #include <utils/Vector.h>
@@ -28,9 +29,9 @@
 struct AMessage;
 class String8;
 
-class AACExtractor : public MediaExtractor {
+class AACExtractor : public MediaExtractorPluginHelper {
 public:
-    AACExtractor(DataSourceBase *source, off64_t offset);
+    AACExtractor(DataSourceHelper *source, off64_t offset);
 
     virtual size_t countTracks();
     virtual MediaTrack *getTrack(size_t index);
@@ -43,7 +44,7 @@
     virtual ~AACExtractor();
 
 private:
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     MetaDataBase mMeta;
     status_t mInitCheck;
 
@@ -55,7 +56,7 @@
 };
 
 bool SniffAAC(
-        DataSourceBase *source, String8 *mimeType, float *confidence, off64_t *offset);
+        DataSourceHelper *source, String8 *mimeType, float *confidence, off64_t *offset);
 
 }  // namespace android
 
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index f56d5ef..e109fb3 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -20,7 +20,6 @@
 
 #include "AMRExtractor.h"
 
-#include <media/DataSourceBase.h>
 #include <media/MediaTrack.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaBufferGroup.h>
@@ -34,7 +33,7 @@
 class AMRSource : public MediaTrack {
 public:
     AMRSource(
-            DataSourceBase *source,
+            DataSourceHelper *source,
             MetaDataBase &meta,
             bool isWide,
             const off64_t *offset_table,
@@ -52,7 +51,7 @@
     virtual ~AMRSource();
 
 private:
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     MetaDataBase mMeta;
     bool mIsWide;
 
@@ -98,7 +97,7 @@
     return frameSize;
 }
 
-static status_t getFrameSizeByOffset(DataSourceBase *source,
+static status_t getFrameSizeByOffset(DataSourceHelper *source,
         off64_t offset, bool isWide, size_t *frameSize) {
     uint8_t header;
     ssize_t count = source->readAt(offset, &header, 1);
@@ -118,7 +117,7 @@
 }
 
 static bool SniffAMR(
-        DataSourceBase *source, bool *isWide, float *confidence) {
+        DataSourceHelper *source, bool *isWide, float *confidence) {
     char header[9];
 
     if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
@@ -144,7 +143,7 @@
     return false;
 }
 
-AMRExtractor::AMRExtractor(DataSourceBase *source)
+AMRExtractor::AMRExtractor(DataSourceHelper *source)
     : mDataSource(source),
       mInitCheck(NO_INIT),
       mOffsetTableLength(0) {
@@ -192,6 +191,7 @@
 }
 
 AMRExtractor::~AMRExtractor() {
+    delete mDataSource;
 }
 
 status_t AMRExtractor::getMetaData(MetaDataBase &meta) {
@@ -229,7 +229,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 AMRSource::AMRSource(
-        DataSourceBase *source, MetaDataBase &meta,
+        DataSourceHelper *source, MetaDataBase &meta,
         bool isWide, const off64_t *offset_table, size_t offset_table_length)
     : mDataSource(source),
       mMeta(meta),
@@ -365,22 +365,23 @@
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
-MediaExtractor::ExtractorDef GETEXTRACTORDEF() {
+ExtractorDef GETEXTRACTORDEF() {
     return {
-        MediaExtractor::EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION,
         UUID("c86639c9-2f31-40ac-a715-fa01b4493aaf"),
         1,
         "AMR Extractor",
         [](
-                DataSourceBase *source,
+                CDataSource *source,
                 float *confidence,
                 void **,
-                MediaExtractor::FreeMetaFunc *) -> MediaExtractor::CreatorFunc {
-            if (SniffAMR(source, nullptr, confidence)) {
+                FreeMetaFunc *) -> CreatorFunc {
+            DataSourceHelper helper(source);
+            if (SniffAMR(&helper, nullptr, confidence)) {
                 return [](
-                        DataSourceBase *source,
-                        void *) -> MediaExtractor* {
-                    return new AMRExtractor(source);};
+                        CDataSource *source,
+                        void *) -> CMediaExtractor* {
+                    return wrap(new AMRExtractor(new DataSourceHelper(source)));};
             }
             return NULL;
         }
diff --git a/media/extractors/amr/AMRExtractor.h b/media/extractors/amr/AMRExtractor.h
index c90b325..499ca67 100644
--- a/media/extractors/amr/AMRExtractor.h
+++ b/media/extractors/amr/AMRExtractor.h
@@ -19,7 +19,8 @@
 #define AMR_EXTRACTOR_H_
 
 #include <utils/Errors.h>
-#include <media/MediaExtractor.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MetaDataBase.h>
 
 namespace android {
@@ -28,9 +29,9 @@
 class String8;
 #define OFFSET_TABLE_LEN    300
 
-class AMRExtractor : public MediaExtractor {
+class AMRExtractor : public MediaExtractorPluginHelper {
 public:
-    explicit AMRExtractor(DataSourceBase *source);
+    explicit AMRExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
     virtual MediaTrack *getTrack(size_t index);
@@ -43,7 +44,7 @@
     virtual ~AMRExtractor();
 
 private:
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     MetaDataBase mMeta;
     status_t mInitCheck;
     bool mIsWide;
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index a721b65..1efaa0c 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -24,7 +24,7 @@
 // libFLAC parser
 #include "FLAC/stream_decoder.h"
 
-#include <media/DataSourceBase.h>
+#include <media/MediaExtractorPluginApi.h>
 #include <media/MediaTrack.h>
 #include <media/VorbisComment.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -43,7 +43,7 @@
 
 public:
     FLACSource(
-            DataSourceBase *dataSource,
+            DataSourceHelper *dataSource,
             MetaDataBase &meta);
 
     virtual status_t start(MetaDataBase *params);
@@ -57,7 +57,7 @@
     virtual ~FLACSource();
 
 private:
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     MetaDataBase mTrackMetadata;
     FLACParser *mParser;
     bool mInitCheck;
@@ -79,7 +79,7 @@
     };
 
     explicit FLACParser(
-        DataSourceBase *dataSource,
+        DataSourceHelper *dataSource,
         // If metadata pointers aren't provided, we don't fill them
         MetaDataBase *fileMetadata = 0,
         MetaDataBase *trackMetadata = 0);
@@ -118,7 +118,7 @@
     }
 
 private:
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     MetaDataBase *mFileMetadata;
     MetaDataBase *mTrackMetadata;
     bool mInitCheck;
@@ -487,7 +487,7 @@
 // FLACParser
 
 FLACParser::FLACParser(
-        DataSourceBase *dataSource,
+        DataSourceHelper *dataSource,
         MetaDataBase *fileMetadata,
         MetaDataBase *trackMetadata)
     : mDataSource(dataSource),
@@ -708,7 +708,7 @@
 // FLACsource
 
 FLACSource::FLACSource(
-        DataSourceBase *dataSource,
+        DataSourceHelper *dataSource,
         MetaDataBase &trackMetadata)
     : mDataSource(dataSource),
       mTrackMetadata(trackMetadata),
@@ -789,7 +789,7 @@
 // FLACExtractor
 
 FLACExtractor::FLACExtractor(
-        DataSourceBase *dataSource)
+        DataSourceHelper *dataSource)
     : mDataSource(dataSource),
       mParser(nullptr),
       mInitCheck(false)
@@ -804,6 +804,7 @@
 {
     ALOGV("~FLACExtractor::FLACExtractor");
     delete mParser;
+    delete mDataSource;
 }
 
 size_t FLACExtractor::countTracks()
@@ -837,7 +838,7 @@
 
 // Sniffer
 
-bool SniffFLAC(DataSourceBase *source, float *confidence)
+bool SniffFLAC(DataSourceHelper *source, float *confidence)
 {
     // first 4 is the signature word
     // second 4 is the sizeof STREAMINFO
@@ -859,22 +860,23 @@
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
-MediaExtractor::ExtractorDef GETEXTRACTORDEF() {
+ExtractorDef GETEXTRACTORDEF() {
     return {
-        MediaExtractor::EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION,
             UUID("1364b048-cc45-4fda-9934-327d0ebf9829"),
             1,
             "FLAC Extractor",
             [](
-                    DataSourceBase *source,
+                    CDataSource *source,
                     float *confidence,
                     void **,
-                    MediaExtractor::FreeMetaFunc *) -> MediaExtractor::CreatorFunc {
-                if (SniffFLAC(source, confidence)) {
+                    FreeMetaFunc *) -> CreatorFunc {
+                DataSourceHelper helper(source);
+                if (SniffFLAC(&helper, confidence)) {
                     return [](
-                            DataSourceBase *source,
-                            void *) -> MediaExtractor* {
-                        return new FLACExtractor(source);};
+                            CDataSource *source,
+                            void *) -> CMediaExtractor* {
+                        return wrap(new FLACExtractor(new DataSourceHelper(source)));};
                 }
                 return NULL;
             }
diff --git a/media/extractors/flac/FLACExtractor.h b/media/extractors/flac/FLACExtractor.h
index 7fb6ec6..1ddff43 100644
--- a/media/extractors/flac/FLACExtractor.h
+++ b/media/extractors/flac/FLACExtractor.h
@@ -18,7 +18,8 @@
 #define FLAC_EXTRACTOR_H_
 
 #include <media/DataSourceBase.h>
-#include <media/MediaExtractor.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MetaDataBase.h>
 #include <utils/String8.h>
 
@@ -26,10 +27,10 @@
 
 class FLACParser;
 
-class FLACExtractor : public MediaExtractor {
+class FLACExtractor : public MediaExtractorPluginHelper {
 
 public:
-    explicit FLACExtractor(DataSourceBase *source);
+    explicit FLACExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
     virtual MediaTrack *getTrack(size_t index);
@@ -42,7 +43,7 @@
     virtual ~FLACExtractor();
 
 private:
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     FLACParser *mParser;
     status_t mInitCheck;
     MetaDataBase mFileMetadata;
@@ -55,8 +56,6 @@
 
 };
 
-bool SniffFLAC(DataSourceBase *source, float *confidence);
-
 }  // namespace android
 
 #endif  // FLAC_EXTRACTOR_H_
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index a30b6f8..233033e 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -142,7 +142,7 @@
 
 // MidiEngine
 
-MidiEngine::MidiEngine(DataSourceBase *dataSource,
+MidiEngine::MidiEngine(CDataSource *dataSource,
         MetaDataBase *fileMetadata,
         MetaDataBase *trackMetadata) :
             mGroup(NULL),
@@ -263,7 +263,7 @@
 // MidiExtractor
 
 MidiExtractor::MidiExtractor(
-        DataSourceBase *dataSource)
+        CDataSource *dataSource)
     : mDataSource(dataSource),
       mInitCheck(false)
 {
@@ -310,7 +310,7 @@
 
 // Sniffer
 
-bool SniffMidi(DataSourceBase *source, float *confidence)
+bool SniffMidi(CDataSource *source, float *confidence)
 {
     MidiEngine p(source, NULL, NULL);
     if (p.initCheck() == OK) {
@@ -326,22 +326,22 @@
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
-MediaExtractor::ExtractorDef GETEXTRACTORDEF() {
+ExtractorDef GETEXTRACTORDEF() {
     return {
-        MediaExtractor::EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION,
         UUID("ef6cca0a-f8a2-43e6-ba5f-dfcd7c9a7ef2"),
         1,
         "MIDI Extractor",
         [](
-                DataSourceBase *source,
+                CDataSource *source,
                 float *confidence,
                 void **,
-                MediaExtractor::FreeMetaFunc *) -> MediaExtractor::CreatorFunc {
+                FreeMetaFunc *) -> CreatorFunc {
             if (SniffMidi(source, confidence)) {
                 return [](
-                        DataSourceBase *source,
-                        void *) -> MediaExtractor* {
-                    return new MidiExtractor(source);};
+                        CDataSource *source,
+                        void *) -> CMediaExtractor* {
+                    return wrap(new MidiExtractor(source));};
             }
             return NULL;
         }
diff --git a/media/extractors/midi/MidiExtractor.h b/media/extractors/midi/MidiExtractor.h
index 244dd0f..fbbe93e 100644
--- a/media/extractors/midi/MidiExtractor.h
+++ b/media/extractors/midi/MidiExtractor.h
@@ -18,7 +18,8 @@
 #define MIDI_EXTRACTOR_H_
 
 #include <media/DataSourceBase.h>
-#include <media/MediaExtractor.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MediaBufferBase.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MetaDataBase.h>
@@ -30,7 +31,7 @@
 
 class MidiEngine {
 public:
-    explicit MidiEngine(DataSourceBase *dataSource,
+    explicit MidiEngine(CDataSource *dataSource,
             MetaDataBase *fileMetadata,
             MetaDataBase *trackMetadata);
     ~MidiEngine();
@@ -50,10 +51,10 @@
     bool mIsInitialized;
 };
 
-class MidiExtractor : public MediaExtractor {
+class MidiExtractor : public MediaExtractorPluginHelper {
 
 public:
-    explicit MidiExtractor(DataSourceBase *source);
+    explicit MidiExtractor(CDataSource *source);
 
     virtual size_t countTracks();
     virtual MediaTrack *getTrack(size_t index);
@@ -66,7 +67,7 @@
     virtual ~MidiExtractor();
 
 private:
-    DataSourceBase *mDataSource;
+    CDataSource *mDataSource;
     status_t mInitCheck;
     MetaDataBase mFileMetadata;
 
@@ -88,7 +89,7 @@
 
 };
 
-bool SniffMidi(DataSourceBase *source, float *confidence);
+bool SniffMidi(CDataSource *source, float *confidence);
 
 }  // namespace android
 
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index d657582..a387970 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -44,7 +44,7 @@
 namespace android {
 
 struct DataSourceBaseReader : public mkvparser::IMkvReader {
-    explicit DataSourceBaseReader(DataSourceBase *source)
+    explicit DataSourceBaseReader(DataSourceHelper *source)
         : mSource(source) {
     }
 
@@ -86,7 +86,7 @@
     }
 
 private:
-    DataSourceBase *mSource;
+    DataSourceHelper *mSource;
 
     DataSourceBaseReader(const DataSourceBaseReader &);
     DataSourceBaseReader &operator=(const DataSourceBaseReader &);
@@ -921,7 +921,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-MatroskaExtractor::MatroskaExtractor(DataSourceBase *source)
+MatroskaExtractor::MatroskaExtractor(DataSourceHelper *source)
     : mDataSource(source),
       mReader(new DataSourceBaseReader(mDataSource)),
       mSegment(NULL),
@@ -994,6 +994,8 @@
 
     delete mReader;
     mReader = NULL;
+
+    delete mDataSource;
 }
 
 size_t MatroskaExtractor::countTracks() {
@@ -1621,7 +1623,7 @@
 }
 
 bool SniffMatroska(
-        DataSourceBase *source, float *confidence) {
+        DataSourceHelper *source, float *confidence) {
     DataSourceBaseReader reader(source);
     mkvparser::EBMLHeader ebmlHeader;
     long long pos;
@@ -1638,22 +1640,23 @@
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
-MediaExtractor::ExtractorDef GETEXTRACTORDEF() {
+ExtractorDef GETEXTRACTORDEF() {
     return {
-        MediaExtractor::EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION,
         UUID("abbedd92-38c4-4904-a4c1-b3f45f899980"),
         1,
         "Matroska Extractor",
         [](
-                DataSourceBase *source,
+                CDataSource *source,
                 float *confidence,
                 void **,
-                MediaExtractor::FreeMetaFunc *) -> MediaExtractor::CreatorFunc {
-            if (SniffMatroska(source, confidence)) {
+                FreeMetaFunc *) -> CreatorFunc {
+            DataSourceHelper helper(source);
+            if (SniffMatroska(&helper, confidence)) {
                 return [](
-                        DataSourceBase *source,
-                        void *) -> MediaExtractor* {
-                    return new MatroskaExtractor(source);};
+                        CDataSource *source,
+                        void *) -> CMediaExtractor* {
+                    return wrap(new MatroskaExtractor(new DataSourceHelper(source)));};
             }
             return NULL;
         }
diff --git a/media/extractors/mkv/MatroskaExtractor.h b/media/extractors/mkv/MatroskaExtractor.h
index 3568ea1..2c6ca85 100644
--- a/media/extractors/mkv/MatroskaExtractor.h
+++ b/media/extractors/mkv/MatroskaExtractor.h
@@ -20,7 +20,8 @@
 
 #include "mkvparser/mkvparser.h"
 
-#include <media/MediaExtractor.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MetaDataBase.h>
 #include <utils/Vector.h>
 #include <utils/threads.h>
@@ -34,8 +35,8 @@
 struct DataSourceBaseReader;
 struct MatroskaSource;
 
-struct MatroskaExtractor : public MediaExtractor {
-    explicit MatroskaExtractor(DataSourceBase *source);
+struct MatroskaExtractor : public MediaExtractorPluginHelper {
+    explicit MatroskaExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
 
@@ -76,7 +77,7 @@
     Mutex mLock;
     Vector<TrackInfo> mTracks;
 
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     DataSourceBaseReader *mReader;
     mkvparser::Segment *mSegment;
     bool mExtractedThumbnails;
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 33cff96..a1e5593 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -24,7 +24,6 @@
 #include "VBRISeeker.h"
 #include "XINGSeeker.h"
 
-#include <media/DataSourceBase.h>
 #include <media/MediaTrack.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -46,7 +45,7 @@
 static const uint32_t kMask = 0xfffe0c00;
 
 static bool Resync(
-        DataSourceBase *source, uint32_t match_header,
+        DataSourceHelper *source, uint32_t match_header,
         off64_t *inout_pos, off64_t *post_id3_pos, uint32_t *out_header) {
     if (post_id3_pos != NULL) {
         *post_id3_pos = 0;
@@ -212,7 +211,7 @@
 class MP3Source : public MediaTrack {
 public:
     MP3Source(
-            MetaDataBase &meta, DataSourceBase *source,
+            MetaDataBase &meta, DataSourceHelper *source,
             off64_t first_frame_pos, uint32_t fixed_header,
             MP3Seeker *seeker);
 
@@ -230,7 +229,7 @@
 private:
     static const size_t kMaxFrameSize;
     MetaDataBase &mMeta;
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     off64_t mFirstFramePos;
     uint32_t mFixedHeader;
     off64_t mCurrentPos;
@@ -253,7 +252,7 @@
 };
 
 MP3Extractor::MP3Extractor(
-        DataSourceBase *source, Mp3Meta *meta)
+        DataSourceHelper *source, Mp3Meta *meta)
     : mInitCheck(NO_INIT),
       mDataSource(source),
       mFirstFramePos(-1),
@@ -371,7 +370,8 @@
     // Get iTunes-style gapless info if present.
     // When getting the id3 tag, skip the V1 tags to prevent the source cache
     // from being iterated to the end of the file.
-    ID3 id3(mDataSource, true);
+    DataSourceHelper helper(mDataSource);
+    ID3 id3(&helper, true);
     if (id3.isValid()) {
         ID3::Iterator *com = new ID3::Iterator(id3, "COM");
         if (com->done()) {
@@ -404,6 +404,7 @@
 
 MP3Extractor::~MP3Extractor() {
     delete mSeeker;
+    delete mDataSource;
 }
 
 size_t MP3Extractor::countTracks() {
@@ -440,7 +441,7 @@
 // Set our max frame size to the nearest power of 2 above this size (aka, 4kB)
 const size_t MP3Source::kMaxFrameSize = (1 << 12); /* 4096 bytes */
 MP3Source::MP3Source(
-        MetaDataBase &meta, DataSourceBase *source,
+        MetaDataBase &meta, DataSourceHelper *source,
         off64_t first_frame_pos, uint32_t fixed_header,
         MP3Seeker *seeker)
     : mMeta(meta),
@@ -612,7 +613,8 @@
     }
     meta.setCString(kKeyMIMEType, "audio/mpeg");
 
-    ID3 id3(mDataSource);
+    DataSourceHelper helper(mDataSource);
+    ID3 id3(&helper);
 
     if (!id3.isValid()) {
         return OK;
@@ -669,21 +671,22 @@
     return OK;
 }
 
-static MediaExtractor* CreateExtractor(
-        DataSourceBase *source,
+static CMediaExtractor* CreateExtractor(
+        CDataSource *source,
         void *meta) {
     Mp3Meta *metaData = static_cast<Mp3Meta *>(meta);
-    return new MP3Extractor(source, metaData);
+    return wrap(new MP3Extractor(new DataSourceHelper(source), metaData));
 }
 
-static MediaExtractor::CreatorFunc Sniff(
-        DataSourceBase *source, float *confidence, void **meta,
-        MediaExtractor::FreeMetaFunc *freeMeta) {
+static CreatorFunc Sniff(
+        CDataSource *source, float *confidence, void **meta,
+        FreeMetaFunc *freeMeta) {
     off64_t pos = 0;
     off64_t post_id3_pos;
     uint32_t header;
     uint8_t mpeg_header[5];
-    if (source->readAt(0, mpeg_header, sizeof(mpeg_header)) < (ssize_t)sizeof(mpeg_header)) {
+    DataSourceHelper helper(source);
+    if (helper.readAt(0, mpeg_header, sizeof(mpeg_header)) < (ssize_t)sizeof(mpeg_header)) {
         return NULL;
     }
 
@@ -691,7 +694,7 @@
         ALOGV("MPEG1PS container is not supported!");
         return NULL;
     }
-    if (!Resync(source, 0, &pos, &post_id3_pos, &header)) {
+    if (!Resync(&helper, 0, &pos, &post_id3_pos, &header)) {
         return NULL;
     }
 
@@ -710,9 +713,9 @@
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
-MediaExtractor::ExtractorDef GETEXTRACTORDEF() {
+ExtractorDef GETEXTRACTORDEF() {
     return {
-        MediaExtractor::EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION,
         UUID("812a3f6c-c8cf-46de-b529-3774b14103d4"),
         1, // version
         "MP3 Extractor",
diff --git a/media/extractors/mp3/MP3Extractor.h b/media/extractors/mp3/MP3Extractor.h
index 485b0ca..585d9f6 100644
--- a/media/extractors/mp3/MP3Extractor.h
+++ b/media/extractors/mp3/MP3Extractor.h
@@ -19,20 +19,22 @@
 #define MP3_EXTRACTOR_H_
 
 #include <utils/Errors.h>
-#include <media/MediaExtractor.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MetaDataBase.h>
 
 namespace android {
 
+class DataSourceHelper;
+
 struct AMessage;
-class DataSourceBase;
 struct MP3Seeker;
 class String8;
 struct Mp3Meta;
 
-class MP3Extractor : public MediaExtractor {
+class MP3Extractor : public MediaExtractorPluginHelper {
 public:
-    MP3Extractor(DataSourceBase *source, Mp3Meta *meta);
+    MP3Extractor(DataSourceHelper *source, Mp3Meta *meta);
     ~MP3Extractor();
 
     virtual size_t countTracks();
@@ -45,7 +47,7 @@
 private:
     status_t mInitCheck;
 
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     off64_t mFirstFramePos;
     MetaDataBase mMeta;
     uint32_t mFixedHeader;
diff --git a/media/extractors/mp3/VBRISeeker.cpp b/media/extractors/mp3/VBRISeeker.cpp
index 523f14c..9eb72a7 100644
--- a/media/extractors/mp3/VBRISeeker.cpp
+++ b/media/extractors/mp3/VBRISeeker.cpp
@@ -27,7 +27,9 @@
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ByteUtils.h>
-#include <media/DataSourceBase.h>
+
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 
 namespace android {
 
@@ -37,7 +39,7 @@
 
 // static
 VBRISeeker *VBRISeeker::CreateFromSource(
-        DataSourceBase *source, off64_t post_id3_pos) {
+        DataSourceHelper *source, off64_t post_id3_pos) {
     off64_t pos = post_id3_pos;
 
     uint8_t header[4];
diff --git a/media/extractors/mp3/VBRISeeker.h b/media/extractors/mp3/VBRISeeker.h
index 9213f6e..507899c 100644
--- a/media/extractors/mp3/VBRISeeker.h
+++ b/media/extractors/mp3/VBRISeeker.h
@@ -24,11 +24,11 @@
 
 namespace android {
 
-class DataSourceBase;
+class DataSourceHelper;
 
 struct VBRISeeker : public MP3Seeker {
     static VBRISeeker *CreateFromSource(
-            DataSourceBase *source, off64_t post_id3_pos);
+            DataSourceHelper *source, off64_t post_id3_pos);
 
     virtual bool getDuration(int64_t *durationUs);
     virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos);
diff --git a/media/extractors/mp3/XINGSeeker.cpp b/media/extractors/mp3/XINGSeeker.cpp
index 01e06ca..9f1fd7a 100644
--- a/media/extractors/mp3/XINGSeeker.cpp
+++ b/media/extractors/mp3/XINGSeeker.cpp
@@ -21,7 +21,9 @@
 #include <media/stagefright/foundation/avc_utils.h>
 
 #include <media/stagefright/foundation/ByteUtils.h>
-#include <media/DataSourceBase.h>
+
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 
 namespace android {
 
@@ -79,7 +81,7 @@
 
 // static
 XINGSeeker *XINGSeeker::CreateFromSource(
-        DataSourceBase *source, off64_t first_frame_pos) {
+        DataSourceHelper *source, off64_t first_frame_pos) {
 
     uint8_t buffer[4];
     int offset = first_frame_pos;
diff --git a/media/extractors/mp3/XINGSeeker.h b/media/extractors/mp3/XINGSeeker.h
index 5867eae..9acee38 100644
--- a/media/extractors/mp3/XINGSeeker.h
+++ b/media/extractors/mp3/XINGSeeker.h
@@ -22,11 +22,11 @@
 
 namespace android {
 
-class DataSourceBase;
+class DataSourceHelper;
 
 struct XINGSeeker : public MP3Seeker {
     static XINGSeeker *CreateFromSource(
-            DataSourceBase *source, off64_t first_frame_pos);
+            DataSourceHelper *source, off64_t first_frame_pos);
 
     virtual bool getDuration(int64_t *durationUs);
     virtual bool getOffsetForTime(int64_t *timeUs, off64_t *pos);
diff --git a/media/extractors/mp4/ItemTable.cpp b/media/extractors/mp4/ItemTable.cpp
index be442e6..a61e60a 100644
--- a/media/extractors/mp4/ItemTable.cpp
+++ b/media/extractors/mp4/ItemTable.cpp
@@ -18,7 +18,8 @@
 #define LOG_TAG "ItemTable"
 
 #include <ItemTable.h>
-#include <media/DataSourceBase.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MetaData.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -92,7 +93,7 @@
 
 struct Box {
 protected:
-    Box(DataSourceBase *source, uint32_t type) :
+    Box(DataSourceHelper *source, uint32_t type) :
         mDataSource(source), mType(type) {}
 
     virtual ~Box() {}
@@ -104,14 +105,14 @@
 
     inline uint32_t type() const { return mType; }
 
-    inline DataSourceBase *source() const { return mDataSource; }
+    inline DataSourceHelper *source() const { return mDataSource; }
 
     status_t parseChunk(off64_t *offset);
 
     status_t parseChunks(off64_t offset, size_t size);
 
 private:
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     uint32_t mType;
 };
 
@@ -186,7 +187,7 @@
 
 struct FullBox : public Box {
 protected:
-    FullBox(DataSourceBase *source, uint32_t type) :
+    FullBox(DataSourceHelper *source, uint32_t type) :
         Box(source, type), mVersion(0), mFlags(0) {}
 
     inline uint8_t version() const { return mVersion; }
@@ -221,7 +222,7 @@
 //
 
 struct PitmBox : public FullBox {
-    PitmBox(DataSourceBase *source) :
+    PitmBox(DataSourceHelper *source) :
         FullBox(source, FOURCC('p', 'i', 't', 'm')) {}
 
     status_t parse(off64_t offset, size_t size, uint32_t *primaryItemId);
@@ -301,7 +302,7 @@
 };
 
 struct IlocBox : public FullBox {
-    IlocBox(DataSourceBase *source, KeyedVector<uint32_t, ItemLoc> *itemLocs) :
+    IlocBox(DataSourceHelper *source, KeyedVector<uint32_t, ItemLoc> *itemLocs) :
         FullBox(source, FOURCC('i', 'l', 'o', 'c')),
         mItemLocs(itemLocs), mHasConstructMethod1(false) {}
 
@@ -471,7 +472,7 @@
 //
 
 struct ItemReference : public Box, public RefBase {
-    ItemReference(DataSourceBase *source, uint32_t type, uint32_t itemIdSize) :
+    ItemReference(DataSourceHelper *source, uint32_t type, uint32_t itemIdSize) :
         Box(source, type), mItemId(0), mRefIdSize(itemIdSize) {}
 
     status_t parse(off64_t offset, size_t size);
@@ -626,7 +627,7 @@
 }
 
 struct IrefBox : public FullBox {
-    IrefBox(DataSourceBase *source, Vector<sp<ItemReference> > *itemRefs) :
+    IrefBox(DataSourceHelper *source, Vector<sp<ItemReference> > *itemRefs) :
         FullBox(source, FOURCC('i', 'r', 'e', 'f')), mRefIdSize(0), mItemRefs(itemRefs) {}
 
     status_t parse(off64_t offset, size_t size);
@@ -688,7 +689,7 @@
 };
 
 struct IspeBox : public FullBox, public ItemProperty {
-    IspeBox(DataSourceBase *source) :
+    IspeBox(DataSourceHelper *source) :
         FullBox(source, FOURCC('i', 's', 'p', 'e')), mWidth(0), mHeight(0) {}
 
     status_t parse(off64_t offset, size_t size) override;
@@ -724,7 +725,7 @@
 }
 
 struct HvccBox : public Box, public ItemProperty {
-    HvccBox(DataSourceBase *source) :
+    HvccBox(DataSourceHelper *source) :
         Box(source, FOURCC('h', 'v', 'c', 'C')) {}
 
     status_t parse(off64_t offset, size_t size) override;
@@ -757,7 +758,7 @@
 }
 
 struct IrotBox : public Box, public ItemProperty {
-    IrotBox(DataSourceBase *source) :
+    IrotBox(DataSourceHelper *source) :
         Box(source, FOURCC('i', 'r', 'o', 't')), mAngle(0) {}
 
     status_t parse(off64_t offset, size_t size) override;
@@ -786,7 +787,7 @@
 }
 
 struct ColrBox : public Box, public ItemProperty {
-    ColrBox(DataSourceBase *source) :
+    ColrBox(DataSourceHelper *source) :
         Box(source, FOURCC('c', 'o', 'l', 'r')) {}
 
     status_t parse(off64_t offset, size_t size) override;
@@ -834,7 +835,7 @@
 }
 
 struct IpmaBox : public FullBox {
-    IpmaBox(DataSourceBase *source, Vector<AssociationEntry> *associations) :
+    IpmaBox(DataSourceHelper *source, Vector<AssociationEntry> *associations) :
         FullBox(source, FOURCC('i', 'p', 'm', 'a')), mAssociations(associations) {}
 
     status_t parse(off64_t offset, size_t size);
@@ -908,7 +909,7 @@
 }
 
 struct IpcoBox : public Box {
-    IpcoBox(DataSourceBase *source, Vector<sp<ItemProperty> > *properties) :
+    IpcoBox(DataSourceHelper *source, Vector<sp<ItemProperty> > *properties) :
         Box(source, FOURCC('i', 'p', 'c', 'o')), mItemProperties(properties) {}
 
     status_t parse(off64_t offset, size_t size);
@@ -965,7 +966,7 @@
 }
 
 struct IprpBox : public Box {
-    IprpBox(DataSourceBase *source,
+    IprpBox(DataSourceHelper *source,
             Vector<sp<ItemProperty> > *properties,
             Vector<AssociationEntry> *associations) :
         Box(source, FOURCC('i', 'p', 'r', 'p')),
@@ -1022,7 +1023,7 @@
 };
 
 struct InfeBox : public FullBox {
-    InfeBox(DataSourceBase *source) :
+    InfeBox(DataSourceHelper *source) :
         FullBox(source, FOURCC('i', 'n', 'f', 'e')) {}
 
     status_t parse(off64_t offset, size_t size, ItemInfo *itemInfo);
@@ -1127,7 +1128,7 @@
 }
 
 struct IinfBox : public FullBox {
-    IinfBox(DataSourceBase *source, Vector<ItemInfo> *itemInfos) :
+    IinfBox(DataSourceHelper *source, Vector<ItemInfo> *itemInfos) :
         FullBox(source, FOURCC('i', 'i', 'n', 'f')),
         mItemInfos(itemInfos), mHasGrids(false) {}
 
@@ -1196,7 +1197,7 @@
 
 //////////////////////////////////////////////////////////////////
 
-ItemTable::ItemTable(DataSourceBase *source)
+ItemTable::ItemTable(DataSourceHelper *source)
     : mDataSource(source),
       mPrimaryItemId(0),
       mIdatOffset(0),
diff --git a/media/extractors/mp4/ItemTable.h b/media/extractors/mp4/ItemTable.h
index 536dcb0..650b3f3 100644
--- a/media/extractors/mp4/ItemTable.h
+++ b/media/extractors/mp4/ItemTable.h
@@ -25,7 +25,7 @@
 
 namespace android {
 
-class DataSourceBase;
+class DataSourceHelper;
 class MetaData;
 
 namespace heif {
@@ -45,7 +45,7 @@
 
 class ItemTable : public RefBase {
 public:
-    explicit ItemTable(DataSourceBase *source);
+    explicit ItemTable(DataSourceHelper *source);
 
     status_t parse(uint32_t type, off64_t offset, size_t size);
 
@@ -62,7 +62,7 @@
     ~ItemTable();
 
 private:
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
 
     KeyedVector<uint32_t, ItemLoc> mItemLocs;
     Vector<ItemInfo> mItemInfos;
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 251a4cd..c02d2fb 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -32,6 +32,7 @@
 #include "ItemTable.h"
 #include "include/ESDS.h"
 
+#include <media/DataSourceBase.h>
 #include <media/ExtractorUtils.h>
 #include <media/MediaTrack.h>
 #include <media/stagefright/foundation/ABitReader.h>
@@ -72,7 +73,7 @@
 public:
     // Caller retains ownership of both "dataSource" and "sampleTable".
     MPEG4Source(MetaDataBase &format,
-                DataSourceBase *dataSource,
+                DataSourceHelper *dataSource,
                 int32_t timeScale,
                 const sp<SampleTable> &sampleTable,
                 Vector<SidxEntry> &sidx,
@@ -96,7 +97,7 @@
     Mutex mLock;
 
     MetaDataBase &mFormat;
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     int32_t mTimescale;
     sp<SampleTable> mSampleTable;
     uint32_t mCurrentSampleIndex;
@@ -197,11 +198,10 @@
 // possibly wrapping multiple times to cover all tracks, i.e.
 // Each CachedRangedDataSource caches the sampletable metadata for a single track.
 
-struct CachedRangedDataSource : public DataSourceBase {
-    explicit CachedRangedDataSource(DataSourceBase *source);
+struct CachedRangedDataSource : public DataSourceHelper {
+    explicit CachedRangedDataSource(DataSourceHelper *source);
     virtual ~CachedRangedDataSource();
 
-    virtual status_t initCheck() const;
     virtual ssize_t readAt(off64_t offset, void *data, size_t size);
     virtual status_t getSize(off64_t *size);
     virtual uint32_t flags();
@@ -212,7 +212,7 @@
 private:
     Mutex mLock;
 
-    DataSourceBase *mSource;
+    DataSourceHelper *mSource;
     bool mOwnsDataSource;
     off64_t mCachedOffset;
     size_t mCachedSize;
@@ -224,8 +224,9 @@
     CachedRangedDataSource &operator=(const CachedRangedDataSource &);
 };
 
-CachedRangedDataSource::CachedRangedDataSource(DataSourceBase *source)
-    : mSource(source),
+CachedRangedDataSource::CachedRangedDataSource(DataSourceHelper *source)
+    : DataSourceHelper(source),
+      mSource(source),
       mOwnsDataSource(false),
       mCachedOffset(0),
       mCachedSize(0),
@@ -249,10 +250,6 @@
     mCachedSize = 0;
 }
 
-status_t CachedRangedDataSource::initCheck() const {
-    return mSource->initCheck();
-}
-
 ssize_t CachedRangedDataSource::readAt(off64_t offset, void *data, size_t size) {
     Mutex::Autolock autoLock(mLock);
 
@@ -364,7 +361,7 @@
     return false;
 }
 
-MPEG4Extractor::MPEG4Extractor(DataSourceBase *source, const char *mime)
+MPEG4Extractor::MPEG4Extractor(DataSourceHelper *source, const char *mime)
     : mMoofOffset(0),
       mMoofFound(false),
       mMdatFound(false),
@@ -397,6 +394,7 @@
     mPssh.clear();
 
     delete mCachedSource;
+    delete mDataSource;
 }
 
 uint32_t MPEG4Extractor::flags() const {
@@ -4093,7 +4091,7 @@
 
 MPEG4Source::MPEG4Source(
         MetaDataBase &format,
-        DataSourceBase *dataSource,
+        DataSourceHelper *dataSource,
         int32_t timeScale,
         const sp<SampleTable> &sampleTable,
         Vector<SidxEntry> &sidx,
@@ -5772,7 +5770,7 @@
     return NULL;
 }
 
-static bool LegacySniffMPEG4(DataSourceBase *source, float *confidence) {
+static bool LegacySniffMPEG4(DataSourceHelper *source, float *confidence) {
     uint8_t header[8];
 
     ssize_t n = source->readAt(4, header, sizeof(header));
@@ -5837,7 +5835,7 @@
 // Also try to identify where this file's metadata ends
 // (end of the 'moov' atom) and report it to the caller as part of
 // the metadata.
-static bool BetterSniffMPEG4(DataSourceBase *source, float *confidence) {
+static bool BetterSniffMPEG4(DataSourceHelper *source, float *confidence) {
     // We scan up to 128 bytes to identify this file as an MP4.
     static const off64_t kMaxScanOffset = 128ll;
 
@@ -5944,18 +5942,19 @@
     return true;
 }
 
-static MediaExtractor* CreateExtractor(DataSourceBase *source, void *) {
-    return new MPEG4Extractor(source);
+static CMediaExtractor* CreateExtractor(CDataSource *source, void *) {
+    return wrap(new MPEG4Extractor(new DataSourceHelper(source)));
 }
 
-static MediaExtractor::CreatorFunc Sniff(
-        DataSourceBase *source, float *confidence, void **,
-        MediaExtractor::FreeMetaFunc *) {
-    if (BetterSniffMPEG4(source, confidence)) {
+static CreatorFunc Sniff(
+        CDataSource *source, float *confidence, void **,
+        FreeMetaFunc *) {
+    DataSourceHelper helper(source);
+    if (BetterSniffMPEG4(&helper, confidence)) {
         return CreateExtractor;
     }
 
-    if (LegacySniffMPEG4(source, confidence)) {
+    if (LegacySniffMPEG4(&helper, confidence)) {
         ALOGW("Identified supported mpeg4 through LegacySniffMPEG4.");
         return CreateExtractor;
     }
@@ -5966,9 +5965,9 @@
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
-MediaExtractor::ExtractorDef GETEXTRACTORDEF() {
+ExtractorDef GETEXTRACTORDEF() {
     return {
-        MediaExtractor::EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION,
         UUID("27575c67-4417-4c54-8d3d-8e626985a164"),
         1, // version
         "MP4 Extractor",
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index a4a5684..ca273e0 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -20,8 +20,8 @@
 
 #include <arpa/inet.h>
 
-#include <media/DataSourceBase.h>
-#include <media/MediaExtractor.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MetaDataBase.h>
 #include <media/stagefright/foundation/AString.h>
 #include <utils/KeyedVector.h>
@@ -31,7 +31,8 @@
 
 namespace android {
 struct AMessage;
-class DataSourceBase;
+struct CDataSource;
+class DataSourceHelper;
 struct CachedRangedDataSource;
 class SampleTable;
 class String8;
@@ -53,9 +54,9 @@
     uint32_t default_sample_flags;
 };
 
-class MPEG4Extractor : public MediaExtractor {
+class MPEG4Extractor : public MediaExtractorPluginHelper {
 public:
-    explicit MPEG4Extractor(DataSourceBase *source, const char *mime = NULL);
+    explicit MPEG4Extractor(DataSourceHelper *source, const char *mime = NULL);
 
     virtual size_t countTracks();
     virtual MediaTrack *getTrack(size_t index);
@@ -97,7 +98,7 @@
 
     Vector<Trex> mTrex;
 
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     CachedRangedDataSource *mCachedSource;
     status_t mInitCheck;
     uint32_t mHeaderTimescale;
@@ -149,10 +150,6 @@
     MPEG4Extractor &operator=(const MPEG4Extractor &);
 };
 
-bool SniffMPEG4(
-        DataSourceBase *source, String8 *mimeType, float *confidence,
-        sp<AMessage> *);
-
 }  // namespace android
 
 #endif  // MPEG4_EXTRACTOR_H_
diff --git a/media/extractors/mp4/SampleTable.cpp b/media/extractors/mp4/SampleTable.cpp
index 28fe717..d242798 100644
--- a/media/extractors/mp4/SampleTable.cpp
+++ b/media/extractors/mp4/SampleTable.cpp
@@ -25,7 +25,7 @@
 
 #include <arpa/inet.h>
 
-#include <media/DataSourceBase.h>
+#include <media/MediaExtractorPluginApi.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ByteUtils.h>
 
@@ -114,7 +114,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-SampleTable::SampleTable(DataSourceBase *source)
+SampleTable::SampleTable(DataSourceHelper *source)
     : mDataSource(source),
       mChunkOffsetOffset(-1),
       mChunkOffsetType(0),
diff --git a/media/extractors/mp4/SampleTable.h b/media/extractors/mp4/SampleTable.h
index dd68860..d4b5dc8 100644
--- a/media/extractors/mp4/SampleTable.h
+++ b/media/extractors/mp4/SampleTable.h
@@ -21,18 +21,19 @@
 #include <sys/types.h>
 #include <stdint.h>
 
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MediaErrors.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
 
 namespace android {
 
-class DataSourceBase;
+class DataSourceHelper;
 struct SampleIterator;
 
 class SampleTable : public RefBase {
 public:
-    explicit SampleTable(DataSourceBase *source);
+    explicit SampleTable(DataSourceHelper *source);
 
     bool isValid() const;
 
@@ -102,7 +103,7 @@
     // Limit the total size of all internal tables to 200MiB.
     static const size_t kMaxTotalSize = 200 * (1 << 20);
 
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     Mutex mLock;
 
     off64_t mChunkOffsetOffset;
diff --git a/media/extractors/mpeg2/ExtractorBundle.cpp b/media/extractors/mpeg2/ExtractorBundle.cpp
index 8a0fa03..ff40ed4 100644
--- a/media/extractors/mpeg2/ExtractorBundle.cpp
+++ b/media/extractors/mpeg2/ExtractorBundle.cpp
@@ -19,35 +19,39 @@
 #include <utils/Log.h>
 
 #include <media/MediaExtractor.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include "MPEG2PSExtractor.h"
 #include "MPEG2TSExtractor.h"
 
 namespace android {
 
+struct CDataSource;
+
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
-MediaExtractor::ExtractorDef GETEXTRACTORDEF() {
+ExtractorDef GETEXTRACTORDEF() {
     return {
-        MediaExtractor::EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION,
         UUID("3d1dcfeb-e40a-436d-a574-c2438a555e5f"),
         1,
         "MPEG2-PS/TS Extractor",
         [](
-                DataSourceBase *source,
+                CDataSource *source,
                 float *confidence,
                 void **,
-                MediaExtractor::FreeMetaFunc *) -> MediaExtractor::CreatorFunc {
-            if (SniffMPEG2TS(source, confidence)) {
+                FreeMetaFunc *) -> CreatorFunc {
+            DataSourceHelper helper(source);
+            if (SniffMPEG2TS(&helper, confidence)) {
                 return [](
-                        DataSourceBase *source,
-                        void *) -> MediaExtractor* {
-                    return new MPEG2TSExtractor(source);};
-            } else if (SniffMPEG2PS(source, confidence)) {
+                        CDataSource *source,
+                        void *) -> CMediaExtractor* {
+                    return wrap(new MPEG2TSExtractor(new DataSourceHelper(source)));};
+            } else if (SniffMPEG2PS(&helper, confidence)) {
                         return [](
-                                DataSourceBase *source,
-                                void *) -> MediaExtractor* {
-                            return new MPEG2PSExtractor(source);};
+                                CDataSource *source,
+                                void *) -> CMediaExtractor* {
+                            return wrap(new MPEG2PSExtractor(new DataSourceHelper(source)));};
             }
             return NULL;
         }
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index 6980b82..ae1e6ba 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -94,7 +94,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-MPEG2PSExtractor::MPEG2PSExtractor(DataSourceBase *source)
+MPEG2PSExtractor::MPEG2PSExtractor(DataSourceHelper *source)
     : mDataSource(source),
       mOffset(0),
       mFinalResult(OK),
@@ -120,6 +120,7 @@
 }
 
 MPEG2PSExtractor::~MPEG2PSExtractor() {
+    delete mDataSource;
 }
 
 size_t MPEG2PSExtractor::countTracks() {
@@ -754,7 +755,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 bool SniffMPEG2PS(
-        DataSourceBase *source, float *confidence) {
+        DataSourceHelper *source, float *confidence) {
     uint8_t header[5];
     if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
         return false;
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.h b/media/extractors/mpeg2/MPEG2PSExtractor.h
index 8b9dad9..7689910 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.h
@@ -19,7 +19,8 @@
 #define MPEG2_PS_EXTRACTOR_H_
 
 #include <media/stagefright/foundation/ABase.h>
-#include <media/MediaExtractor.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MetaDataBase.h>
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
@@ -31,8 +32,8 @@
 struct Track;
 class String8;
 
-struct MPEG2PSExtractor : public MediaExtractor {
-    explicit MPEG2PSExtractor(DataSourceBase *source);
+struct MPEG2PSExtractor : public MediaExtractorPluginHelper {
+    explicit MPEG2PSExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
     virtual MediaTrack *getTrack(size_t index);
@@ -51,7 +52,7 @@
     struct WrappedTrack;
 
     mutable Mutex mLock;
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
 
     off64_t mOffset;
     status_t mFinalResult;
@@ -72,7 +73,7 @@
     DISALLOW_EVIL_CONSTRUCTORS(MPEG2PSExtractor);
 };
 
-bool SniffMPEG2PS(DataSourceBase *source, float *confidence);
+bool SniffMPEG2PS(DataSourceHelper *source, float *confidence);
 
 }  // namespace android
 
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index c83f7ce..cbe8556 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -123,7 +123,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-MPEG2TSExtractor::MPEG2TSExtractor(DataSourceBase *source)
+MPEG2TSExtractor::MPEG2TSExtractor(DataSourceHelper *source)
     : mDataSource(source),
       mParser(new ATSParser),
       mLastSyncEvent(0),
@@ -131,6 +131,10 @@
     init();
 }
 
+MPEG2TSExtractor::~MPEG2TSExtractor() {
+    delete mDataSource;
+}
+
 size_t MPEG2TSExtractor::countTracks() {
     return mSourceImpls.size();
 }
@@ -652,7 +656,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-bool SniffMPEG2TS(DataSourceBase *source, float *confidence) {
+bool SniffMPEG2TS(DataSourceHelper *source, float *confidence) {
     for (int i = 0; i < 5; ++i) {
         char header;
         if (source->readAt(kTSPacketSize * i, &header, 1) != 1
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.h b/media/extractors/mpeg2/MPEG2TSExtractor.h
index cbdd3cb..cdaede3 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.h
@@ -20,7 +20,8 @@
 #define MPEG2_TS_EXTRACTOR_H_
 
 #include <media/stagefright/foundation/ABase.h>
-#include <media/MediaExtractor.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/MediaTrack.h>
 #include <media/stagefright/MetaDataBase.h>
 #include <utils/threads.h>
@@ -34,12 +35,12 @@
 struct AMessage;
 struct AnotherPacketSource;
 struct ATSParser;
-class DataSourceBase;
+struct CDataSource;
 struct MPEG2TSSource;
 class String8;
 
-struct MPEG2TSExtractor : public MediaExtractor {
-    explicit MPEG2TSExtractor(DataSourceBase *source);
+struct MPEG2TSExtractor : public MediaExtractorPluginHelper {
+    explicit MPEG2TSExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
     virtual MediaTrack *getTrack(size_t index);
@@ -52,12 +53,15 @@
     virtual uint32_t flags() const;
     virtual const char * name() { return "MPEG2TSExtractor"; }
 
+protected:
+    virtual ~MPEG2TSExtractor();
+
 private:
     friend struct MPEG2TSSource;
 
     mutable Mutex mLock;
 
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
 
     sp<ATSParser> mParser;
 
@@ -81,9 +85,9 @@
     // Try to feed more data from source to parser.
     // |isInit| means this function is called inside init(). This is a signal to
     // save SyncEvent so that init() can add SyncPoint after it updates |mSourceImpls|.
-    // This function returns OK if expected amount of data is fed from DataSourceBase to
+    // This function returns OK if expected amount of data is fed from DataSourceHelper to
     // parser and is successfully parsed. Otherwise, various error codes could be
-    // returned, e.g., ERROR_END_OF_STREAM, or no data availalbe from DataSourceBase, or
+    // returned, e.g., ERROR_END_OF_STREAM, or no data availalbe from DataSourceHelper, or
     // the data has syntax error during parsing, etc.
     status_t feedMore(bool isInit = false);
     status_t seek(int64_t seekTimeUs,
@@ -101,7 +105,7 @@
     DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSExtractor);
 };
 
-bool SniffMPEG2TS(DataSourceBase *source, float *confidence);
+bool SniffMPEG2TS(DataSourceHelper *source, float *confidence);
 
 }  // namespace android
 
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index b2fe69c..4e97921 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -71,7 +71,7 @@
 
 struct MyOggExtractor {
     MyOggExtractor(
-            DataSourceBase *source,
+            DataSourceHelper *source,
             const char *mimeType,
             size_t numHeaders,
             int64_t seekPreRollUs);
@@ -110,7 +110,7 @@
         int64_t mTimeUs;
     };
 
-    DataSourceBase *mSource;
+    DataSourceHelper *mSource;
     off64_t mOffset;
     Page mCurrentPage;
     uint64_t mCurGranulePosition;
@@ -169,7 +169,7 @@
 };
 
 struct MyVorbisExtractor : public MyOggExtractor {
-    explicit MyVorbisExtractor(DataSourceBase *source)
+    explicit MyVorbisExtractor(DataSourceHelper *source)
         : MyOggExtractor(source,
                 MEDIA_MIMETYPE_AUDIO_VORBIS,
                 /* numHeaders */ 3,
@@ -197,7 +197,7 @@
     static const int32_t kOpusSampleRate = 48000;
     static const int64_t kOpusSeekPreRollUs = 80000; // 80 ms
 
-    explicit MyOpusExtractor(DataSourceBase *source)
+    explicit MyOpusExtractor(DataSourceHelper *source)
         : MyOggExtractor(source, MEDIA_MIMETYPE_AUDIO_OPUS, /*numHeaders*/ 2, kOpusSeekPreRollUs),
           mChannelCount(0),
           mCodecDelay(0),
@@ -296,7 +296,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MyOggExtractor::MyOggExtractor(
-        DataSourceBase *source,
+        DataSourceHelper *source,
         const char *mimeType,
         size_t numHeaders,
         int64_t seekPreRollUs)
@@ -1193,7 +1193,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-OggExtractor::OggExtractor(DataSourceBase *source)
+OggExtractor::OggExtractor(DataSourceHelper *source)
     : mDataSource(source),
       mInitCheck(NO_INIT),
       mImpl(NULL) {
@@ -1220,6 +1220,7 @@
 OggExtractor::~OggExtractor() {
     delete mImpl;
     mImpl = NULL;
+    delete mDataSource;
 }
 
 size_t OggExtractor::countTracks() {
@@ -1248,19 +1249,20 @@
     return mImpl->getFileMetaData(meta);
 }
 
-static MediaExtractor* CreateExtractor(
-        DataSourceBase *source,
+static CMediaExtractor* CreateExtractor(
+        CDataSource *source,
         void *) {
-    return new OggExtractor(source);
+    return wrap(new OggExtractor(new DataSourceHelper(source)));
 }
 
-static MediaExtractor::CreatorFunc Sniff(
-        DataSourceBase *source,
+static CreatorFunc Sniff(
+        CDataSource *source,
         float *confidence,
         void **,
-        MediaExtractor::FreeMetaFunc *) {
+        FreeMetaFunc *) {
+    DataSourceHelper helper(source);
     char tmp[4];
-    if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
+    if (helper.readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
         return NULL;
     }
 
@@ -1272,9 +1274,9 @@
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
-MediaExtractor::ExtractorDef GETEXTRACTORDEF() {
+ExtractorDef GETEXTRACTORDEF() {
     return {
-        MediaExtractor::EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION,
         UUID("8cc5cd06-f772-495e-8a62-cba9649374e9"),
         1, // version
         "Ogg Extractor",
diff --git a/media/extractors/ogg/OggExtractor.h b/media/extractors/ogg/OggExtractor.h
index 9fe2944..fbd4663 100644
--- a/media/extractors/ogg/OggExtractor.h
+++ b/media/extractors/ogg/OggExtractor.h
@@ -19,19 +19,19 @@
 #define OGG_EXTRACTOR_H_
 
 #include <utils/Errors.h>
-#include <media/MediaExtractor.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 
 namespace android {
 
 struct AMessage;
-class DataSourceBase;
 class String8;
 
 struct MyOggExtractor;
 struct OggSource;
 
-struct OggExtractor : public MediaExtractor {
-    explicit OggExtractor(DataSourceBase *source);
+struct OggExtractor : public MediaExtractorPluginHelper {
+    explicit OggExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
     virtual MediaTrack *getTrack(size_t index);
@@ -46,7 +46,7 @@
 private:
     friend struct OggSource;
 
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     status_t mInitCheck;
 
     MyOggExtractor *mImpl;
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index f5a1b01..c739c2a 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -57,7 +57,7 @@
 
 struct WAVSource : public MediaTrack {
     WAVSource(
-            DataSourceBase *dataSource,
+            DataSourceHelper *dataSource,
             MetaDataBase &meta,
             uint16_t waveFormat,
             int32_t bitsPerSample,
@@ -78,7 +78,7 @@
 private:
     static const size_t kMaxFrameSize;
 
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     MetaDataBase &mMeta;
     uint16_t mWaveFormat;
     int32_t mSampleRate;
@@ -94,7 +94,7 @@
     WAVSource &operator=(const WAVSource &);
 };
 
-WAVExtractor::WAVExtractor(DataSourceBase *source)
+WAVExtractor::WAVExtractor(DataSourceHelper *source)
     : mDataSource(source),
       mValidFormat(false),
       mChannelMask(CHANNEL_MASK_USE_CHANNEL_ORDER) {
@@ -102,6 +102,7 @@
 }
 
 WAVExtractor::~WAVExtractor() {
+    delete mDataSource;
 }
 
 status_t WAVExtractor::getMetaData(MetaDataBase &meta) {
@@ -347,7 +348,7 @@
 const size_t WAVSource::kMaxFrameSize = 32768;
 
 WAVSource::WAVSource(
-        DataSourceBase *dataSource,
+        DataSourceHelper *dataSource,
         MetaDataBase &meta,
         uint16_t waveFormat,
         int32_t bitsPerSample,
@@ -544,27 +545,30 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-static MediaExtractor* CreateExtractor(
-        DataSourceBase *source,
+static CMediaExtractor* CreateExtractor(
+        CDataSource *source,
         void *) {
-    return new WAVExtractor(source);
+    return wrap(new WAVExtractor(new DataSourceHelper(source)));
 }
 
-static MediaExtractor::CreatorFunc Sniff(
-        DataSourceBase *source,
+static CreatorFunc Sniff(
+        CDataSource *source,
         float *confidence,
         void **,
-        MediaExtractor::FreeMetaFunc *) {
+        FreeMetaFunc *) {
+    DataSourceHelper *helper = new DataSourceHelper(source);
     char header[12];
-    if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
+    if (helper->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
+        delete helper;
         return NULL;
     }
 
     if (memcmp(header, "RIFF", 4) || memcmp(&header[8], "WAVE", 4)) {
+        delete helper;
         return NULL;
     }
 
-    MediaExtractor *extractor = new WAVExtractor(source);
+    WAVExtractor *extractor = new WAVExtractor(helper); // extractor owns the helper
     int numTracks = extractor->countTracks();
     delete extractor;
     if (numTracks == 0) {
@@ -579,9 +583,9 @@
 extern "C" {
 // This is the only symbol that needs to be exported
 __attribute__ ((visibility ("default")))
-MediaExtractor::ExtractorDef GETEXTRACTORDEF() {
+ExtractorDef GETEXTRACTORDEF() {
     return {
-        MediaExtractor::EXTRACTORDEF_VERSION,
+        EXTRACTORDEF_VERSION,
         UUID("7d613858-5837-4a38-84c5-332d1cddee27"),
         1, // version
         "WAV Extractor",
diff --git a/media/extractors/wav/WAVExtractor.h b/media/extractors/wav/WAVExtractor.h
index 467d0b7..5136aa8 100644
--- a/media/extractors/wav/WAVExtractor.h
+++ b/media/extractors/wav/WAVExtractor.h
@@ -19,18 +19,19 @@
 #define WAV_EXTRACTOR_H_
 
 #include <utils/Errors.h>
-#include <media/MediaExtractor.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/MetaDataBase.h>
 
 namespace android {
 
 struct AMessage;
-class DataSourceBase;
+struct CDataSource;
 class String8;
 
-class WAVExtractor : public MediaExtractor {
+class WAVExtractor : public MediaExtractorPluginHelper {
 public:
-    explicit WAVExtractor(DataSourceBase *source);
+    explicit WAVExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
     virtual MediaTrack *getTrack(size_t index);
@@ -42,7 +43,7 @@
     virtual ~WAVExtractor();
 
 private:
-    DataSourceBase *mDataSource;
+    DataSourceHelper *mDataSource;
     status_t mInitCheck;
     bool mValidFormat;
     uint16_t mWaveFormat;
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index da7d85e..cf11936 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -458,6 +458,38 @@
     return NO_ERROR;
 }
 
+status_t AudioEffect::addSourceDefaultEffect(const char *typeStr,
+                                             const String16& opPackageName,
+                                             const char *uuidStr,
+                                             int32_t priority,
+                                             audio_source_t source,
+                                             audio_unique_id_t *id)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+
+    if (typeStr == NULL && uuidStr == NULL) return BAD_VALUE;
+
+    // Convert type & uuid from string to effect_uuid_t.
+    effect_uuid_t type;
+    if (typeStr != NULL) {
+        status_t res = stringToGuid(typeStr, &type);
+        if (res != OK) return res;
+    } else {
+        type = *EFFECT_UUID_NULL;
+    }
+
+    effect_uuid_t uuid;
+    if (uuidStr != NULL) {
+        status_t res = stringToGuid(uuidStr, &uuid);
+        if (res != OK) return res;
+    } else {
+        uuid = *EFFECT_UUID_NULL;
+    }
+
+    return aps->addSourceDefaultEffect(&type, opPackageName, &uuid, priority, source, id);
+}
+
 status_t AudioEffect::addStreamDefaultEffect(const char *typeStr,
                                              const String16& opPackageName,
                                              const char *uuidStr,
@@ -490,6 +522,14 @@
     return aps->addStreamDefaultEffect(&type, opPackageName, &uuid, priority, usage, id);
 }
 
+status_t AudioEffect::removeSourceDefaultEffect(audio_unique_id_t id)
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return PERMISSION_DENIED;
+
+    return aps->removeSourceDefaultEffect(id);
+}
+
 status_t AudioEffect::removeStreamDefaultEffect(audio_unique_id_t id)
 {
     const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index f9df5b1..e2de8e7 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -865,9 +865,9 @@
     } else if (waitCount == 0) {
         requested = &ClientProxy::kNonBlocking;
     } else if (waitCount > 0) {
-        long long ms = WAIT_PERIOD_MS * (long long) waitCount;
+        time_t ms = WAIT_PERIOD_MS * (time_t) waitCount;
         timeout.tv_sec = ms / 1000;
-        timeout.tv_nsec = (int) (ms % 1000) * 1000000;
+        timeout.tv_nsec = (long) (ms % 1000) * 1000000;
         requested = &timeout;
     } else {
         ALOGE("%s invalid waitCount %d", __func__, waitCount);
diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp
index ab9efe8..76c9bfb 100644
--- a/media/libaudioclient/AudioTrack.cpp
+++ b/media/libaudioclient/AudioTrack.cpp
@@ -706,6 +706,13 @@
         // force refresh of remaining frames by processAudioBuffer() as last
         // write before stop could be partial.
         mRefreshRemaining = true;
+
+        // for static track, clear the old flags when starting from stopped state
+        if (mSharedBuffer != 0) {
+            android_atomic_and(
+            ~(CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL | CBLK_BUFFER_END),
+            &mCblk->mFlags);
+        }
     }
     mNewPosition = mPosition + mUpdatePeriod;
     int32_t flags = android_atomic_and(~(CBLK_STREAM_END_DONE | CBLK_DISABLED), &mCblk->mFlags);
@@ -1634,9 +1641,9 @@
     } else if (waitCount == 0) {
         requested = &ClientProxy::kNonBlocking;
     } else if (waitCount > 0) {
-        long long ms = WAIT_PERIOD_MS * (long long) waitCount;
+        time_t ms = WAIT_PERIOD_MS * (time_t) waitCount;
         timeout.tv_sec = ms / 1000;
-        timeout.tv_nsec = (int) (ms % 1000) * 1000000;
+        timeout.tv_nsec = (long) (ms % 1000) * 1000000;
         requested = &timeout;
     } else {
         ALOGE("%s invalid waitCount %d", __func__, waitCount);
diff --git a/media/libaudioclient/AudioTrackShared.cpp b/media/libaudioclient/AudioTrackShared.cpp
index a018b22..b8156c6 100644
--- a/media/libaudioclient/AudioTrackShared.cpp
+++ b/media/libaudioclient/AudioTrackShared.cpp
@@ -286,7 +286,8 @@
                 struct timespec after;
                 clock_gettime(CLOCK_MONOTONIC, &after);
                 total.tv_sec += after.tv_sec - before.tv_sec;
-                long deltaNs = after.tv_nsec - before.tv_nsec;
+                // Use auto instead of long to avoid the google-runtime-int warning.
+                auto deltaNs = after.tv_nsec - before.tv_nsec;
                 if (deltaNs < 0) {
                     deltaNs += 1000000000;
                     total.tv_sec--;
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index abf74f8..32a71f3 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -83,7 +83,9 @@
     GET_SURROUND_FORMATS,
     SET_SURROUND_FORMAT_ENABLED,
     ADD_STREAM_DEFAULT_EFFECT,
-    REMOVE_STREAM_DEFAULT_EFFECT
+    REMOVE_STREAM_DEFAULT_EFFECT,
+    ADD_SOURCE_DEFAULT_EFFECT,
+    REMOVE_SOURCE_DEFAULT_EFFECT
 };
 
 #define MAX_ITEMS_PER_LIST 1024
@@ -904,6 +906,41 @@
         return static_cast <status_t> (reply.readInt32());
     }
 
+    virtual status_t addSourceDefaultEffect(const effect_uuid_t *type,
+                                            const String16& opPackageName,
+                                            const effect_uuid_t *uuid,
+                                            int32_t priority,
+                                            audio_source_t source,
+                                            audio_unique_id_t* id)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.write(type, sizeof(effect_uuid_t));
+        data.writeString16(opPackageName);
+        data.write(uuid, sizeof(effect_uuid_t));
+        data.writeInt32(priority);
+        data.writeInt32((int32_t) source);
+        status_t status = remote()->transact(ADD_SOURCE_DEFAULT_EFFECT, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        status = static_cast <status_t> (reply.readInt32());
+        *id = reply.readInt32();
+        return status;
+    }
+
+    virtual status_t removeSourceDefaultEffect(audio_unique_id_t id)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        data.writeInt32(id);
+        status_t status = remote()->transact(REMOVE_SOURCE_DEFAULT_EFFECT, data, &reply);
+        if (status != NO_ERROR) {
+            return status;
+        }
+        return static_cast <status_t> (reply.readInt32());
+    }
+
 };
 
 IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1636,6 +1673,43 @@
             return NO_ERROR;
         }
 
+        case ADD_SOURCE_DEFAULT_EFFECT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            effect_uuid_t type;
+            status_t status = data.read(&type, sizeof(effect_uuid_t));
+            if (status != NO_ERROR) {
+                return status;
+            }
+            String16 opPackageName;
+            status = data.readString16(&opPackageName);
+            if (status != NO_ERROR) {
+                return status;
+            }
+            effect_uuid_t uuid;
+            status = data.read(&uuid, sizeof(effect_uuid_t));
+            if (status != NO_ERROR) {
+                return status;
+            }
+            int32_t priority = data.readInt32();
+            audio_source_t source = (audio_source_t) data.readInt32();
+            audio_unique_id_t id = 0;
+            reply->writeInt32(static_cast <int32_t>(addSourceDefaultEffect(&type,
+                                                                           opPackageName,
+                                                                           &uuid,
+                                                                           priority,
+                                                                           source,
+                                                                           &id)));
+            reply->writeInt32(id);
+            return NO_ERROR;
+        }
+
+        case REMOVE_SOURCE_DEFAULT_EFFECT: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            audio_unique_id_t id = static_cast<audio_unique_id_t>(data.readInt32());
+            reply->writeInt32(static_cast <int32_t>(removeSourceDefaultEffect(id)));
+            return NO_ERROR;
+        }
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libaudioclient/ToneGenerator.cpp b/media/libaudioclient/ToneGenerator.cpp
index 5716727..c9263f4 100644
--- a/media/libaudioclient/ToneGenerator.cpp
+++ b/media/libaudioclient/ToneGenerator.cpp
@@ -1136,13 +1136,13 @@
             // This is needed in case of cold start of the output stream.
             if ((mStartTime.tv_sec != 0) && (clock_gettime(CLOCK_MONOTONIC, &stopTime) == 0)) {
                 time_t sec = stopTime.tv_sec - mStartTime.tv_sec;
-                long nsec = stopTime.tv_nsec - mStartTime.tv_nsec;
+                auto nsec = stopTime.tv_nsec - mStartTime.tv_nsec;
                 if (nsec < 0) {
                     --sec;
                     nsec += 1000000000;
                 }
 
-                if ((sec + 1) > ((long)(INT_MAX / mSamplingRate))) {
+                if ((sec + 1) > ((time_t)(INT_MAX / mSamplingRate))) {
                     mMaxSmp = sec * mSamplingRate;
                 } else {
                     // mSamplingRate is always > 1000
@@ -1257,8 +1257,8 @@
 
     AudioTrack::Buffer *buffer = static_cast<AudioTrack::Buffer *>(info);
     ToneGenerator *lpToneGen = static_cast<ToneGenerator *>(user);
-    short *lpOut = buffer->i16;
-    unsigned int lNumSmp = buffer->size/sizeof(short);
+    int16_t *lpOut = buffer->i16;
+    unsigned int lNumSmp = buffer->size/sizeof(int16_t);
     const ToneDescriptor *lpToneDesc = lpToneGen->mpToneDesc;
 
     if (buffer->size == 0) return;
@@ -1329,7 +1329,7 @@
             if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] != 0) {
                 lWaveCmd = WaveGenerator::WAVEGEN_STOP;
                 unsigned int lFreqIdx = 0;
-                unsigned short lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
+                uint16_t lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
 
                 while (lFrequency != 0) {
                     WaveGenerator *lpWaveGen = lpToneGen->mWaveGens.valueFor(lFrequency);
@@ -1379,16 +1379,18 @@
                         lWaveCmd = WaveGenerator::WAVEGEN_START;
                     }
 
-                    ALOGV("New segment %d, Next Time: %d", lpToneGen->mCurSegment,
-                            (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
+                    ALOGV("New segment %d, Next Time: %lld", lpToneGen->mCurSegment,
+                            ((long long)(lpToneGen->mNextSegSmp)*1000)/lpToneGen->mSamplingRate);
+
 
                 } else {
                     lGenSmp = 0;
                     ALOGV("End repeat, time: %d", (unsigned int)(systemTime()/1000000));
                 }
             } else {
-                ALOGV("New segment %d, Next Time: %d", lpToneGen->mCurSegment,
-                        (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
+                ALOGV("New segment %d, Next Time: %lld", lpToneGen->mCurSegment,
+                        ((long long)(lpToneGen->mNextSegSmp)*1000)/lpToneGen->mSamplingRate);
+
                 if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] != 0) {
                     // If next segment is not silent,  OFF -> ON transition : reset wave generator
                     lWaveCmd = WaveGenerator::WAVEGEN_START;
@@ -1415,7 +1417,7 @@
         if (lGenSmp) {
             // If samples must be generated, call all active wave generators and acumulate waves in lpOut
             unsigned int lFreqIdx = 0;
-            unsigned short lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
+            uint16_t lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
 
             while (lFrequency != 0) {
                 WaveGenerator *lpWaveGen = lpToneGen->mWaveGens.valueFor(lFrequency);
@@ -1654,17 +1656,17 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 ToneGenerator::WaveGenerator::WaveGenerator(uint32_t samplingRate,
-        unsigned short frequency, float volume) {
+        uint16_t frequency, float volume) {
     double d0;
     double F_div_Fs;  // frequency / samplingRate
 
     F_div_Fs = frequency / (double)samplingRate;
     d0 = - (float)GEN_AMP * sin(2 * M_PI * F_div_Fs);
-    mS2_0 = (short)d0;
+    mS2_0 = (int16_t)d0;
     mS1 = 0;
     mS2 = mS2_0;
 
-    mAmplitude_Q15 = (short)(32767. * 32767. * volume / GEN_AMP);
+    mAmplitude_Q15 = (int16_t)(32767. * 32767. * volume / GEN_AMP);
     // take some margin for amplitude fluctuation
     if (mAmplitude_Q15 > 32500)
         mAmplitude_Q15 = 32500;
@@ -1672,7 +1674,7 @@
     d0 = 32768.0 * cos(2 * M_PI * F_div_Fs);  // Q14*2*cos()
     if (d0 > 32767)
         d0 = 32767;
-    mA1_Q14 = (short) d0;
+    mA1_Q14 = (int16_t) d0;
 
     ALOGV("WaveGenerator init, mA1_Q14: %d, mS2_0: %d, mAmplitude_Q15: %d",
             mA1_Q14, mS2_0, mAmplitude_Q15);
@@ -1710,7 +1712,7 @@
 //        none
 //
 ////////////////////////////////////////////////////////////////////////////////
-void ToneGenerator::WaveGenerator::getSamples(short *outBuffer,
+void ToneGenerator::WaveGenerator::getSamples(int16_t *outBuffer,
         unsigned int count, unsigned int command) {
     long lS1, lS2;
     long lA1, lAmplitude;
@@ -1741,7 +1743,7 @@
             lS2 = lS1;
             lS1 = Sample;
             Sample = ((lAmplitude>>16) * Sample) >> S_Q15;
-            *(outBuffer++) += (short)Sample;  // put result in buffer
+            *(outBuffer++) += (int16_t)Sample;  // put result in buffer
             lAmplitude -= dec;
         }
     } else {
@@ -1753,7 +1755,7 @@
             lS2 = lS1;
             lS1 = Sample;
             Sample = (lAmplitude * Sample) >> S_Q15;
-            *(outBuffer++) += (short)Sample;  // put result in buffer
+            *(outBuffer++) += (int16_t)Sample;  // put result in buffer
         }
     }
 
diff --git a/media/libaudioclient/include/media/AudioEffect.h b/media/libaudioclient/include/media/AudioEffect.h
index 58a9baa..6bd4137 100644
--- a/media/libaudioclient/include/media/AudioEffect.h
+++ b/media/libaudioclient/include/media/AudioEffect.h
@@ -170,6 +170,44 @@
      */
 
     /*
+     * Adds an effect to the list of default output effects for a given source type.
+     *
+     * If the effect is no longer available when a source of the given type
+     * is created, the system will continue without adding it.
+     *
+     * Parameters:
+     *   typeStr:  Type uuid of effect to be a default: can be null if uuidStr is specified.
+     *             This may correspond to the OpenSL ES interface implemented by this effect,
+     *             or could be some vendor-defined type.
+     *   opPackageName: The package name used for app op checks.
+     *   uuidStr:  Uuid of effect to be a default: can be null if type is specified.
+     *             This uuid corresponds to a particular implementation of an effect type.
+     *             Note if both uuidStr and typeStr are specified, typeStr is ignored.
+     *   priority: Requested priority for effect control: the priority level corresponds to the
+     *             value of priority parameter: negative values indicate lower priorities, positive
+     *             values higher priorities, 0 being the normal priority.
+     *   source:   The source this effect should be a default for.
+     *   id:       Address where the system-wide unique id of the default effect should be returned.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *      NO_ERROR        successful operation.
+     *      PERMISSION_DENIED could not get AudioFlinger interface
+     *                        or caller lacks required permissions.
+     *      NO_INIT         effect library failed to initialize.
+     *      BAD_VALUE       invalid source, type uuid or implementation uuid.
+     *      NAME_NOT_FOUND  no effect with this uuid or type found.
+     *
+     * Returned value
+     *   *id:  The system-wide unique id of the added default effect.
+     */
+    static status_t addSourceDefaultEffect(const char* typeStr,
+                                           const String16& opPackageName,
+                                           const char* uuidStr,
+                                           int32_t priority,
+                                           audio_source_t source,
+                                           audio_unique_id_t* id);
+
+    /*
      * Adds an effect to the list of default output effects for a given stream type.
      *
      * If the effect is no longer available when a stream of the given type
@@ -209,6 +247,21 @@
                                            audio_unique_id_t* id);
 
     /*
+     * Removes an effect from the list of default output effects for a given source type.
+     *
+     * Parameters:
+     *      id: The system-wide unique id of the effect that should no longer be a default.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *      NO_ERROR        successful operation.
+     *      PERMISSION_DENIED could not get AudioFlinger interface
+     *                        or caller lacks required permissions.
+     *      NO_INIT         effect library failed to initialize.
+     *      BAD_VALUE       invalid id.
+     */
+    static status_t removeSourceDefaultEffect(audio_unique_id_t id);
+
+    /*
      * Removes an effect from the list of default output effects for a given stream type.
      *
      * Parameters:
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index cf446a5..806280a 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -85,7 +85,7 @@
 
         union {
             void*       raw;
-            short*      i16;        // signed 16-bit
+            int16_t*    i16;        // signed 16-bit
             int8_t*     i8;         // unsigned 8-bit, offset by 0x80
                                     // input to obtainBuffer(): unused, output: pointer to buffer
         };
diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h
index 3eb627d..59c6f4c 100644
--- a/media/libaudioclient/include/media/AudioTrack.h
+++ b/media/libaudioclient/include/media/AudioTrack.h
@@ -102,7 +102,7 @@
 
         union {
             void*       raw;
-            short*      i16;      // signed 16-bit
+            int16_t*    i16;      // signed 16-bit
             int8_t*     i8;       // unsigned 8-bit, offset by 0x80
         };                        // input to obtainBuffer(): unused, output: pointer to buffer
     };
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index c2899f8..fdd8d57 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -109,12 +109,19 @@
     virtual status_t queryDefaultPreProcessing(audio_session_t audioSession,
                                               effect_descriptor_t *descriptors,
                                               uint32_t *count) = 0;
+    virtual status_t addSourceDefaultEffect(const effect_uuid_t *type,
+                                            const String16& opPackageName,
+                                            const effect_uuid_t *uuid,
+                                            int32_t priority,
+                                            audio_source_t source,
+                                            audio_unique_id_t* id) = 0;
     virtual status_t addStreamDefaultEffect(const effect_uuid_t *type,
                                             const String16& opPackageName,
                                             const effect_uuid_t *uuid,
                                             int32_t priority,
                                             audio_usage_t usage,
                                             audio_unique_id_t* id) = 0;
+    virtual status_t removeSourceDefaultEffect(audio_unique_id_t id) = 0;
     virtual status_t removeStreamDefaultEffect(audio_unique_id_t id) = 0;
    // Check if offload is possible for given format, stream type, sample rate,
     // bit rate, duration, video and streaming or offload property is enabled
diff --git a/media/libaudioclient/include/media/ToneGenerator.h b/media/libaudioclient/include/media/ToneGenerator.h
index 247703f..e0e3bb1 100644
--- a/media/libaudioclient/include/media/ToneGenerator.h
+++ b/media/libaudioclient/include/media/ToneGenerator.h
@@ -256,9 +256,9 @@
     class ToneSegment {
     public:
         unsigned int duration;
-        unsigned short waveFreq[TONEGEN_MAX_WAVES+1];
-        unsigned short loopCnt;
-        unsigned short loopIndx;
+        uint16_t waveFreq[TONEGEN_MAX_WAVES+1];
+        uint16_t loopCnt;
+        uint16_t loopIndx;
     };
 
     class ToneDescriptor {
@@ -279,14 +279,14 @@
     unsigned int mMaxSmp;  // Maximum number of audio samples played (maximun tone duration)
     int mDurationMs;  // Maximum tone duration in ms
 
-    unsigned short mCurSegment;  // Current segment index in ToneDescriptor segments[]
-    unsigned short mCurCount;  // Current sequence repeat count
-    volatile unsigned short mState;  // ToneGenerator state (tone_state)
-    unsigned short mRegion;
+    uint16_t mCurSegment;  // Current segment index in ToneDescriptor segments[]
+    uint16_t mCurCount;  // Current sequence repeat count
+    volatile uint16_t mState;  // ToneGenerator state (tone_state)
+    uint16_t mRegion;
     const ToneDescriptor *mpToneDesc;  // pointer to active tone descriptor
     const ToneDescriptor *mpNewToneDesc;  // pointer to next active tone descriptor
 
-    unsigned short mLoopCounter; // Current tone loopback count
+    uint16_t mLoopCounter; // Current tone loopback count
 
     uint32_t mSamplingRate;  // AudioFlinger Sampling rate
     sp<AudioTrack> mpAudioTrack;  // Pointer to audio track used for playback
@@ -314,26 +314,26 @@
             WAVEGEN_STOP  // Stop wave on zero crossing
         };
 
-        WaveGenerator(uint32_t samplingRate, unsigned short frequency,
+        WaveGenerator(uint32_t samplingRate, uint16_t frequency,
                 float volume);
         ~WaveGenerator();
 
-        void getSamples(short *outBuffer, unsigned int count,
+        void getSamples(int16_t *outBuffer, unsigned int count,
                 unsigned int command);
 
     private:
-        static const short GEN_AMP = 32000;  // amplitude of generator
-        static const short S_Q14 = 14;  // shift for Q14
-        static const short S_Q15 = 15;  // shift for Q15
+        static const int16_t GEN_AMP = 32000;  // amplitude of generator
+        static const int16_t S_Q14 = 14;  // shift for Q14
+        static const int16_t S_Q15 = 15;  // shift for Q15
 
-        short mA1_Q14;  // Q14 coefficient
+        int16_t mA1_Q14;  // Q14 coefficient
         // delay line of full amplitude generator
         long mS1, mS2;  // delay line S2 oldest
-        short mS2_0;  // saved value for reinitialisation
-        short mAmplitude_Q15;  // Q15 amplitude
+        int16_t mS2_0;  // saved value for reinitialisation
+        int16_t mAmplitude_Q15;  // Q15 amplitude
     };
 
-    KeyedVector<unsigned short, WaveGenerator *> mWaveGens;  // list of active wave generators.
+    KeyedVector<uint16_t, WaveGenerator *> mWaveGens;  // list of active wave generators.
 };
 
 }
diff --git a/media/libmedia/MidiIoWrapper.cpp b/media/libmedia/MidiIoWrapper.cpp
index 5ca3b48..1150d61 100644
--- a/media/libmedia/MidiIoWrapper.cpp
+++ b/media/libmedia/MidiIoWrapper.cpp
@@ -23,6 +23,7 @@
 #include <fcntl.h>
 
 #include <media/MidiIoWrapper.h>
+#include <media/MediaExtractorPluginApi.h>
 
 static int readAt(void *handle, void *buffer, int pos, int size) {
     return ((android::MidiIoWrapper*)handle)->readAt(buffer, pos, size);
@@ -61,6 +62,51 @@
     }
 }
 
+class DataSourceUnwrapper : public DataSourceBase {
+
+public:
+    explicit DataSourceUnwrapper(CDataSource *csource) {
+        mSource = csource;
+    }
+    virtual status_t initCheck() const { return OK; }
+
+    // Returns the number of bytes read, or -1 on failure. It's not an error if
+    // this returns zero; it just means the given offset is equal to, or
+    // beyond, the end of the source.
+    virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
+        return mSource->readAt(mSource->handle, offset, data, size);
+    }
+
+    // May return ERROR_UNSUPPORTED.
+    virtual status_t getSize(off64_t *size) {
+        return mSource->getSize(mSource->handle, size);
+    }
+
+    virtual bool getUri(char * /*uriString*/, size_t /*bufferSize*/) {
+        return false;
+    }
+
+    virtual uint32_t flags() {
+        return 0;
+    }
+
+    virtual void close() {};
+private:
+    CDataSource *mSource;
+};
+
+MidiIoWrapper::MidiIoWrapper(CDataSource *csource) {
+    ALOGV("MidiIoWrapper(CDataSource)");
+    mFd = -1;
+    mDataSource = new DataSourceUnwrapper(csource);
+    off64_t l;
+    if (mDataSource->getSize(&l) == OK) {
+        mLength = l;
+    } else {
+        mLength = 0;
+    }
+}
+
 MidiIoWrapper::~MidiIoWrapper() {
     ALOGV("~MidiIoWrapper");
     if (mFd >= 0) {
diff --git a/media/libmedia/include/media/MidiIoWrapper.h b/media/libmedia/include/media/MidiIoWrapper.h
index b5e565e..6309dda 100644
--- a/media/libmedia/include/media/MidiIoWrapper.h
+++ b/media/libmedia/include/media/MidiIoWrapper.h
@@ -23,11 +23,14 @@
 
 namespace android {
 
+struct CDataSource;
+
 class MidiIoWrapper {
 public:
     explicit MidiIoWrapper(const char *path);
     explicit MidiIoWrapper(int fd, off64_t offset, int64_t size);
     explicit MidiIoWrapper(DataSourceBase *source);
+    explicit MidiIoWrapper(CDataSource *csource);
 
     ~MidiIoWrapper();
 
diff --git a/media/libmediaextractor/MediaExtractor.cpp b/media/libmediaextractor/MediaExtractor.cpp
index a6b3dc9..8bf44c8 100644
--- a/media/libmediaextractor/MediaExtractor.cpp
+++ b/media/libmediaextractor/MediaExtractor.cpp
@@ -39,4 +39,43 @@
     return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE | CAN_SEEK;
 }
 
+// --------------------------------------------------------------------------------
+MediaExtractorCUnwrapper::MediaExtractorCUnwrapper(CMediaExtractor *wrapper) {
+    this->wrapper = wrapper;
+}
+
+MediaExtractorCUnwrapper::~MediaExtractorCUnwrapper() {
+    wrapper->free(wrapper->data);
+    free(wrapper);
+}
+
+size_t MediaExtractorCUnwrapper::countTracks() {
+    return wrapper->countTracks(wrapper->data);
+}
+
+MediaTrack *MediaExtractorCUnwrapper::getTrack(size_t index) {
+    return wrapper->getTrack(wrapper->data, index);
+}
+
+status_t MediaExtractorCUnwrapper::getTrackMetaData(
+        MetaDataBase& meta, size_t index, uint32_t flags) {
+    return wrapper->getTrackMetaData(wrapper->data, meta, index, flags);
+}
+
+status_t MediaExtractorCUnwrapper::getMetaData(MetaDataBase& meta) {
+    return wrapper->getMetaData(wrapper->data, meta);
+}
+
+const char * MediaExtractorCUnwrapper::name() {
+    return wrapper->name(wrapper->data);
+}
+
+uint32_t MediaExtractorCUnwrapper::flags() const {
+    return wrapper->flags(wrapper->data);
+}
+
+status_t MediaExtractorCUnwrapper::setMediaCas(const uint8_t* casToken, size_t size) {
+    return wrapper->setMediaCas(wrapper->data, casToken, size);
+}
+
 }  // namespace android
diff --git a/media/libmediaextractor/include/media/DataSource.h b/media/libmediaextractor/include/media/DataSource.h
index 0e59f39..cb96ff5 100644
--- a/media/libmediaextractor/include/media/DataSource.h
+++ b/media/libmediaextractor/include/media/DataSource.h
@@ -22,6 +22,7 @@
 #include <media/stagefright/MediaErrors.h>
 #include <media/DataSourceBase.h>
 #include <media/IDataSource.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 #include <utils/threads.h>
@@ -34,7 +35,7 @@
 
 class DataSource : public DataSourceBase, public virtual RefBase {
 public:
-    DataSource() {}
+    DataSource() : mWrapper(NULL) {}
 
     // returns a pointer to IDataSource if it is wrapped.
     virtual sp<IDataSource> getIDataSource() const {
@@ -69,10 +70,35 @@
         return String8("application/octet-stream");
     }
 
+    CDataSource *wrap() {
+        if (mWrapper) {
+            return mWrapper;
+        }
+        mWrapper = new CDataSource();
+        mWrapper->handle = this;
+
+        mWrapper->readAt = [](void *handle, off64_t offset, void *data, size_t size) -> ssize_t {
+            return ((DataSource*)handle)->readAt(offset, data, size);
+        };
+        mWrapper->getSize = [](void *handle, off64_t *size) -> status_t {
+            return ((DataSource*)handle)->getSize(size);
+        };
+        mWrapper->flags = [](void *handle) -> uint32_t {
+            return ((DataSource*)handle)->flags();
+        };
+        mWrapper->getUri = [](void *handle, char *uriString, size_t bufferSize) -> bool {
+            return ((DataSource*)handle)->getUri(uriString, bufferSize);
+        };
+        return mWrapper;
+    }
+
 protected:
-    virtual ~DataSource() {}
+    virtual ~DataSource() {
+        delete mWrapper;
+    }
 
 private:
+    CDataSource *mWrapper;
     DataSource(const DataSource &);
     DataSource &operator=(const DataSource &);
 };
diff --git a/media/libmediaextractor/include/media/MediaExtractor.h b/media/libmediaextractor/include/media/MediaExtractor.h
index 4ba98da..d9456ab 100644
--- a/media/libmediaextractor/include/media/MediaExtractor.h
+++ b/media/libmediaextractor/include/media/MediaExtractor.h
@@ -24,6 +24,8 @@
 #include <utils/Errors.h>
 #include <utils/Log.h>
 #include <utils/RefBase.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 
 namespace android {
 
@@ -42,7 +44,6 @@
     }
 };
 
-
 class MediaExtractor
 // : public ExtractorAllocTracker
 {
@@ -79,46 +80,6 @@
 
     virtual const char * name() { return "<unspecified>"; }
 
-    typedef MediaExtractor* (*CreatorFunc)(
-            DataSourceBase *source, void *meta);
-    typedef void (*FreeMetaFunc)(void *meta);
-
-    // The sniffer can optionally fill in an opaque object, "meta", that helps
-    // the corresponding extractor initialize its state without duplicating
-    // effort already exerted by the sniffer. If "freeMeta" is given, it will be
-    // called against the opaque object when it is no longer used.
-    typedef CreatorFunc (*SnifferFunc)(
-            DataSourceBase *source, float *confidence,
-            void **meta, FreeMetaFunc *freeMeta);
-
-    typedef struct {
-        const uint8_t b[16];
-    } uuid_t;
-
-    typedef struct {
-        // version number of this structure
-        const uint32_t def_version;
-
-        // A unique identifier for this extractor.
-        // See below for a convenience macro to create this from a string.
-        uuid_t extractor_uuid;
-
-        // Version number of this extractor. When two extractors with the same
-        // uuid are encountered, the one with the largest version number will
-        // be used.
-        const uint32_t extractor_version;
-
-        // a human readable name
-        const char *extractor_name;
-
-        // the sniffer function
-        const SnifferFunc sniff;
-    } ExtractorDef;
-
-    static const uint32_t EXTRACTORDEF_VERSION = 1;
-
-    typedef ExtractorDef (*GetExtractorDef)();
-
 protected:
     MediaExtractor();
 
@@ -127,66 +88,21 @@
     MediaExtractor &operator=(const MediaExtractor &);
 };
 
-// purposely not defined anywhere so that this will fail to link if
-// expressions below are not evaluated at compile time
-int invalid_uuid_string(const char *);
-
-template <typename T, size_t N>
-constexpr uint8_t _digitAt_(const T (&s)[N], const size_t n) {
-    return s[n] >= '0' && s[n] <= '9' ? s[n] - '0'
-            : s[n] >= 'a' && s[n] <= 'f' ? s[n] - 'a' + 10
-                    : s[n] >= 'A' && s[n] <= 'F' ? s[n] - 'A' + 10
-                            : invalid_uuid_string("uuid: bad digits");
-}
-
-template <typename T, size_t N>
-constexpr uint8_t _hexByteAt_(const T (&s)[N], size_t n) {
-    return (_digitAt_(s, n) << 4) + _digitAt_(s, n + 1);
-}
-
-constexpr bool _assertIsDash_(char c) {
-    return c == '-' ? true : invalid_uuid_string("Wrong format");
-}
-
-template <size_t N>
-constexpr MediaExtractor::uuid_t constUUID(const char (&s) [N]) {
-    static_assert(N == 37, "uuid: wrong length");
-    return
-            _assertIsDash_(s[8]),
-            _assertIsDash_(s[13]),
-            _assertIsDash_(s[18]),
-            _assertIsDash_(s[23]),
-            MediaExtractor::uuid_t {{
-                _hexByteAt_(s, 0),
-                _hexByteAt_(s, 2),
-                _hexByteAt_(s, 4),
-                _hexByteAt_(s, 6),
-                _hexByteAt_(s, 9),
-                _hexByteAt_(s, 11),
-                _hexByteAt_(s, 14),
-                _hexByteAt_(s, 16),
-                _hexByteAt_(s, 19),
-                _hexByteAt_(s, 21),
-                _hexByteAt_(s, 24),
-                _hexByteAt_(s, 26),
-                _hexByteAt_(s, 28),
-                _hexByteAt_(s, 30),
-                _hexByteAt_(s, 32),
-                _hexByteAt_(s, 34),
-            }};
-}
-// Convenience macro to create a uuid_t from a string literal, which should
-// be formatted as "12345678-1234-1234-1234-123456789abc", as generated by
-// e.g. https://www.uuidgenerator.net/ or the 'uuidgen' linux command.
-// Hex digits may be upper or lower case.
-//
-// The macro call is otherwise equivalent to specifying the structure directly
-// (e.g. UUID("7d613858-5837-4a38-84c5-332d1cddee27") is the same as
-//       {{0x7d, 0x61, 0x38, 0x58, 0x58, 0x37, 0x4a, 0x38,
-//         0x84, 0xc5, 0x33, 0x2d, 0x1c, 0xdd, 0xee, 0x27}})
-
-#define UUID(str) []{ constexpr MediaExtractor::uuid_t uuid = constUUID(str); return uuid; }()
-
+class MediaExtractorCUnwrapper : public MediaExtractor {
+public:
+    explicit MediaExtractorCUnwrapper(CMediaExtractor *wrapper);
+    virtual size_t countTracks();
+    virtual MediaTrack *getTrack(size_t index);
+    virtual status_t getTrackMetaData(MetaDataBase& meta, size_t index, uint32_t flags = 0);
+    virtual status_t getMetaData(MetaDataBase& meta);
+    virtual const char * name();
+    virtual uint32_t flags() const;
+    virtual status_t setMediaCas(const uint8_t* casToken, size_t size);
+protected:
+    virtual ~MediaExtractorCUnwrapper();
+private:
+    CMediaExtractor *wrapper;
+};
 
 
 }  // namespace android
diff --git a/media/libnblog/NBLog.cpp b/media/libnblog/NBLog.cpp
index f5d2d6d..d659445 100644
--- a/media/libnblog/NBLog.cpp
+++ b/media/libnblog/NBLog.cpp
@@ -20,11 +20,7 @@
 
 #include <algorithm>
 #include <climits>
-#include <deque>
-#include <fstream>
-#include <iostream>
 #include <math.h>
-#include <numeric>
 #include <unordered_set>
 #include <vector>
 #include <stdarg.h>
@@ -727,7 +723,7 @@
 };
 
 NBLog::Reader::Reader(const void *shared, size_t size, const std::string &name)
-    : mFd(-1), mIndent(0), mLost(0), mName(name),
+    : mName(name),
       mShared((/*const*/ Shared *) shared), /*mIMemory*/
       mFifo(mShared != NULL ?
         new audio_utils_fifo(size, sizeof(uint8_t),
@@ -769,10 +765,10 @@
 // Copies content of a Reader FIFO into its Snapshot
 // The Snapshot has the same raw data, but represented as a sequence of entries
 // and an EntryIterator making it possible to process the data.
-std::unique_ptr<NBLog::Reader::Snapshot> NBLog::Reader::getSnapshot()
+std::unique_ptr<NBLog::Snapshot> NBLog::Reader::getSnapshot()
 {
     if (mFifoReader == NULL) {
-        return std::unique_ptr<NBLog::Reader::Snapshot>(new Snapshot());
+        return std::make_unique<Snapshot>();
     }
 
     // This emulates the behaviour of audio_utils_fifo_reader::read, but without incrementing the
@@ -802,7 +798,7 @@
 
     if (availToRead <= 0) {
         ALOGW_IF(availToRead < 0, "NBLog Reader %s failed to catch up with Writer", mName.c_str());
-        return std::make_unique<NBLog::Reader::Snapshot>();
+        return std::make_unique<Snapshot>();
     }
 
     std::unique_ptr<Snapshot> snapshot(new Snapshot(availToRead));
@@ -853,17 +849,12 @@
 
 // Takes raw content of the local merger FIFO, processes log entries, and
 // writes the data to a map of class PerformanceAnalysis, based on their thread ID.
-void NBLog::MergeReader::getAndProcessSnapshot(NBLog::Reader::Snapshot &snapshot)
+void NBLog::MergeReader::getAndProcessSnapshot(NBLog::Snapshot &snapshot, int author)
 {
-    String8 timestamp, body;
-
-    for (auto entry = snapshot.begin(); entry != snapshot.end();) {
-        switch (entry->type) {
-        case EVENT_START_FMT:
-            entry = handleFormat(FormatEntry(entry), &timestamp, &body);
-            break;
+    for (const entry &etr : snapshot) {
+        switch (etr.type) {
         case EVENT_HISTOGRAM_ENTRY_TS: {
-            HistTsEntryWithAuthor *data = (HistTsEntryWithAuthor *) (entry->data);
+            HistTsEntry *data = (HistTsEntry *) (etr.data);
             // TODO This memcpies are here to avoid unaligned memory access crash.
             // There's probably a more efficient way to do it
             log_hash_t hash;
@@ -872,45 +863,41 @@
             memcpy(&ts, &data->ts, sizeof(ts));
             // TODO: hash for histogram ts and audio state need to match
             // and correspond to audio production source file location
-            mThreadPerformanceAnalysis[data->author][0 /*hash*/].logTsEntry(ts);
-            ++entry;
-            break;
-        }
+            mThreadPerformanceAnalysis[author][0 /*hash*/].logTsEntry(ts);
+        } break;
         case EVENT_AUDIO_STATE: {
-            HistTsEntryWithAuthor *data = (HistTsEntryWithAuthor *) (entry->data);
+            HistTsEntry *data = (HistTsEntry *) (etr.data);
             // TODO This memcpies are here to avoid unaligned memory access crash.
             // There's probably a more efficient way to do it
             log_hash_t hash;
             memcpy(&hash, &(data->hash), sizeof(hash));
-            // TODO: remove ts if unused
-            int64_t ts;
-            memcpy(&ts, &data->ts, sizeof(ts));
-            mThreadPerformanceAnalysis[data->author][0 /*hash*/].handleStateChange();
-            ++entry;
-            break;
-        }
+            mThreadPerformanceAnalysis[author][0 /*hash*/].handleStateChange();
+        } break;
         case EVENT_END_FMT:
-            body.appendFormat("warning: got to end format event");
-            ++entry;
-            break;
         case EVENT_RESERVED:
+        case EVENT_UPPER_BOUND:
+            ALOGW("warning: unexpected event %d", etr.type);
         default:
-            body.appendFormat("warning: unexpected event %d", entry->type);
-            ++entry;
             break;
         }
     }
-    // FIXME: decide whether to print the warnings here or elsewhere
-    if (!body.isEmpty()) {
-        dumpLine(&timestamp, &body);
-    }
 }
 
 void NBLog::MergeReader::getAndProcessSnapshot()
 {
-    // get a snapshot, process it
-    std::unique_ptr<Snapshot> snap = getSnapshot();
-    getAndProcessSnapshot(*snap);
+    // get a snapshot of each reader and process them
+    // TODO insert lock here
+    const size_t nLogs = mReaders.size();
+    std::vector<std::unique_ptr<Snapshot>> snapshots(nLogs);
+    for (size_t i = 0; i < nLogs; i++) {
+        snapshots[i] = mReaders[i]->getSnapshot();
+    }
+    // TODO unlock lock here
+    for (size_t i = 0; i < nLogs; i++) {
+        if (snapshots[i] != nullptr) {
+            getAndProcessSnapshot(*(snapshots[i]), i);
+        }
+    }
 }
 
 void NBLog::MergeReader::dump(int fd, int indent)
@@ -919,66 +906,41 @@
     ReportPerformance::dump(fd, indent, mThreadPerformanceAnalysis);
 }
 
-void NBLog::Reader::dump(int fd, size_t indent, NBLog::Reader::Snapshot &snapshot)
+// TODO for future compatibility, would prefer to have a dump() go to string, and then go
+// to fd only when invoked through binder.
+void NBLog::DumpReader::dump(int fd, size_t indent)
 {
-    mFd = fd;
-    mIndent = indent;
-    String8 timestamp, body;
-
-    // Range-based for loop isn't used here because handleFormat() returns an EntryIterator
-    // that points to the next entry (it handles all of the necessary operator++() calls).
-    for (auto entry = snapshot.begin(); entry != snapshot.end();) {
-        switch (entry->type) {
-        case EVENT_START_FMT:
-            entry = handleFormat(FormatEntry(entry), &timestamp, &body);
-            break;
-        case EVENT_HISTOGRAM_ENTRY_TS:
-            ++entry;
-            break;
-        case EVENT_AUDIO_STATE:
-            ++entry;
-            break;
-        case EVENT_END_FMT:
-            body.appendFormat("warning: got to end format event");
-            ++entry;
-            break;
-        case EVENT_MONOTONIC_CYCLE_TIME: {
-            uint32_t monotonicNs = *(uint32_t *) (entry->data);
-            body.appendFormat("Thread cycle took %u ns", monotonicNs);
-            ++entry;
-        } break;
-        case EVENT_RESERVED:
-        default:
-            body.appendFormat("warning: unexpected event %d", entry->type);
-            ++entry;
-            break;
-        }
-        // FIXME: decide whether to print the warnings here or elsewhere
-        if (!body.isEmpty()) {
-            dumpLine(&timestamp, &body);
-        }
-    }
-}
-
-void NBLog::Reader::dump(int fd, size_t indent)
-{
-    // get a snapshot, dump it
-    std::unique_ptr<Snapshot> snap = getSnapshot();
-    dump(fd, indent, *snap);
-}
-
-// Writes a string to the console
-void NBLog::Reader::dumpLine(const String8 *timestamp, String8 *body)
-{
-    if (timestamp == nullptr || body == nullptr) {
+    if (fd < 0) return;
+    std::unique_ptr<Snapshot> snapshot = getSnapshot();
+    if (snapshot == nullptr) {
         return;
     }
-    if (mFd >= 0) {
-        dprintf(mFd, "%.*s%s %s\n", mIndent, "", timestamp->string(), body->string());
-    } else {
-        ALOGI("%.*s%s %s", mIndent, "", timestamp->string(), body->string());
+    String8 timestamp, body;
+
+    // TODO all logged types should have a printable format.
+    for (auto it = snapshot->begin(); it != snapshot->end(); ++it) {
+        switch (it->type) {
+        case EVENT_START_FMT:
+            it = handleFormat(FormatEntry(it), &timestamp, &body);
+            break;
+        case EVENT_MONOTONIC_CYCLE_TIME: {
+            uint32_t monotonicNs;
+            memcpy(&monotonicNs, it->data, sizeof(monotonicNs));
+            body.appendFormat("Thread cycle took %u ns", monotonicNs);
+        } break;
+        case EVENT_END_FMT:
+        case EVENT_RESERVED:
+        case EVENT_UPPER_BOUND:
+            body.appendFormat("warning: unexpected event %d", it->type);
+        default:
+            break;
+        }
+        if (!body.isEmpty()) {
+            dprintf(fd, "%.*s%s %s\n", (int)indent, "", timestamp.string(), body.string());
+            body.clear();
+        }
+        timestamp.clear();
     }
-    body->clear();
 }
 
 bool NBLog::Reader::isIMemory(const sp<IMemory>& iMemory) const
@@ -986,9 +948,7 @@
     return iMemory != 0 && mIMemory != 0 && iMemory->pointer() == mIMemory->pointer();
 }
 
-// ---------------------------------------------------------------------------
-
-void NBLog::appendTimestamp(String8 *body, const void *data)
+void NBLog::DumpReader::appendTimestamp(String8 *body, const void *data)
 {
     if (body == nullptr || data == nullptr) {
         return;
@@ -999,7 +959,7 @@
                     (int) ((ts / (1000 * 1000)) % 1000));
 }
 
-void NBLog::appendInt(String8 *body, const void *data)
+void NBLog::DumpReader::appendInt(String8 *body, const void *data)
 {
     if (body == nullptr || data == nullptr) {
         return;
@@ -1008,7 +968,7 @@
     body->appendFormat("<%d>", x);
 }
 
-void NBLog::appendFloat(String8 *body, const void *data)
+void NBLog::DumpReader::appendFloat(String8 *body, const void *data)
 {
     if (body == nullptr || data == nullptr) {
         return;
@@ -1018,7 +978,7 @@
     body->appendFormat("<%f>", f);
 }
 
-void NBLog::appendPID(String8 *body, const void* data, size_t length)
+void NBLog::DumpReader::appendPID(String8 *body, const void* data, size_t length)
 {
     if (body == nullptr || data == nullptr) {
         return;
@@ -1028,7 +988,7 @@
     body->appendFormat("<PID: %d, name: %.*s>", id, (int) (length - sizeof(pid_t)), name);
 }
 
-String8 NBLog::bufferDump(const uint8_t *buffer, size_t size)
+String8 NBLog::DumpReader::bufferDump(const uint8_t *buffer, size_t size)
 {
     String8 str;
     if (buffer == nullptr) {
@@ -1042,14 +1002,14 @@
     return str;
 }
 
-String8 NBLog::bufferDump(const EntryIterator &it)
+String8 NBLog::DumpReader::bufferDump(const EntryIterator &it)
 {
     return bufferDump(it, it->length + Entry::kOverhead);
 }
 
-NBLog::EntryIterator NBLog::Reader::handleFormat(const FormatEntry &fmtEntry,
-                                                         String8 *timestamp,
-                                                         String8 *body)
+NBLog::EntryIterator NBLog::DumpReader::handleFormat(const FormatEntry &fmtEntry,
+                                                           String8 *timestamp,
+                                                           String8 *body)
 {
     // log timestamp
     int64_t ts = fmtEntry.timestamp();
@@ -1135,7 +1095,6 @@
         ++arg;
     }
     ALOGW_IF(arg->type != EVENT_END_FMT, "Expected end of format, got %d", arg->type);
-    ++arg;
     return arg;
 }
 
@@ -1172,10 +1131,10 @@
 // Merge registered readers, sorted by timestamp, and write data to a single FIFO in local memory
 void NBLog::Merger::merge()
 {
-    // FIXME This is called by merge thread
-    //       but the access to shared variable mNamedReaders is not yet protected by a lock.
+    if (true) return; // Merging is not necessary at the moment, so this is to disable it
+                      // and bypass compiler warnings about member variables not being used.
     const int nLogs = mReaders.size();
-    std::vector<std::unique_ptr<NBLog::Reader::Snapshot>> snapshots(nLogs);
+    std::vector<std::unique_ptr<Snapshot>> snapshots(nLogs);
     std::vector<EntryIterator> offsets;
     offsets.reserve(nLogs);
     for (int i = 0; i < nLogs; ++i) {
@@ -1258,13 +1217,12 @@
     {
         AutoMutex _l(mMutex);
         // If mTimeoutUs is negative, wait on the condition variable until it's positive.
-        // If it's positive, wait kThreadSleepPeriodUs and then merge
-        nsecs_t waitTime = mTimeoutUs > 0 ? kThreadSleepPeriodUs * 1000 : LLONG_MAX;
-        mCond.waitRelative(mMutex, waitTime);
+        // If it's positive, merge. The minimum period between waking the condition variable
+        // is handled in AudioFlinger::MediaLogNotifier::threadLoop().
+        mCond.wait(mMutex);
         doMerge = mTimeoutUs > 0;
         mTimeoutUs -= kThreadSleepPeriodUs;
     }
-    doMerge = false;    // Disable merging for now.
     if (doMerge) {
         // Merge data from all the readers
         mMerger.merge();
diff --git a/media/libnblog/include/media/nblog/NBLog.h b/media/libnblog/include/media/nblog/NBLog.h
index 71941a4..c9bfaae 100644
--- a/media/libnblog/include/media/nblog/NBLog.h
+++ b/media/libnblog/include/media/nblog/NBLog.h
@@ -19,7 +19,6 @@
 #ifndef ANDROID_MEDIA_NBLOG_H
 #define ANDROID_MEDIA_NBLOG_H
 
-#include <deque>
 #include <map>
 #include <unordered_set>
 #include <vector>
@@ -76,17 +75,6 @@
 private:
 
     // ---------------------------------------------------------------------------
-    // API for handling format entry operations
-
-    // a formatted entry has the following structure:
-    //    * START_FMT entry, containing the format string
-    //    * TIMESTAMP entry
-    //    * HASH entry
-    //    * author entry of the thread that generated it (optional, present in merged log)
-    //    * format arg1
-    //    * format arg2
-    //    * ...
-    //    * END_FMT entry
 
     // entry representation in memory
     struct entry {
@@ -144,6 +132,9 @@
         const uint8_t  *mPtr;   // Should not be nullptr except for dummy initialization
     };
 
+    // ---------------------------------------------------------------------------
+    // The following classes are used for merging into the Merger's buffer.
+
     class AbstractEntry {
     public:
         virtual ~AbstractEntry() {}
@@ -175,6 +166,17 @@
         const uint8_t  *mEntry;
     };
 
+    // API for handling format entry operations
+
+    // a formatted entry has the following structure:
+    //    * START_FMT entry, containing the format string
+    //    * TIMESTAMP entry
+    //    * HASH entry
+    //    * author entry of the thread that generated it (optional, present in merged log)
+    //    * format arg1
+    //    * format arg2
+    //    * ...
+    //    * END_FMT entry
     class FormatEntry : public AbstractEntry {
     public:
         // explicit FormatEntry(const EntryIterator &it);
@@ -226,7 +228,16 @@
 
     // ---------------------------------------------------------------------------
 
-    // representation of a single log entry in private memory
+    // representation of a single log entry in shared memory
+    //  byte[0]             mEvent
+    //  byte[1]             mLength
+    //  byte[2]             mData[0]
+    //  ...
+    //  byte[2+i]           mData[i]
+    //  ...
+    //  byte[2+mLength-1]   mData[mLength-1]
+    //  byte[2+mLength]     duplicate copy of mLength to permit reverse scan
+    //  byte[3+mLength]     start of next log entry
     class Entry {
     public:
         Entry(Event event, const void *data, size_t length)
@@ -267,24 +278,6 @@
         int value;
     }; //TODO __attribute__((packed));
 
-    // representation of a single log entry in shared memory
-    //  byte[0]             mEvent
-    //  byte[1]             mLength
-    //  byte[2]             mData[0]
-    //  ...
-    //  byte[2+i]           mData[i]
-    //  ...
-    //  byte[2+mLength-1]   mData[mLength-1]
-    //  byte[2+mLength]     duplicate copy of mLength to permit reverse scan
-    //  byte[3+mLength]     start of next log entry
-
-    static void    appendInt(String8 *body, const void *data);
-    static void    appendFloat(String8 *body, const void *data);
-    static void    appendPID(String8 *body, const void *data, size_t length);
-    static void    appendTimestamp(String8 *body, const void *data);
-    static size_t  fmtEntryLength(const uint8_t *data);
-    static String8 bufferDump(const uint8_t *buffer, size_t size);
-    static String8 bufferDump(const EntryIterator &it);
 public:
 
     // Located in shared memory, must be POD.
@@ -420,89 +413,86 @@
 
     // ---------------------------------------------------------------------------
 
+    // A snapshot of a readers buffer
+    // This is raw data. No analysis has been done on it
+    class Snapshot {
+    public:
+        Snapshot() = default;
+
+        explicit Snapshot(size_t bufferSize) : mData(new uint8_t[bufferSize]) {}
+
+        ~Snapshot() { delete[] mData; }
+
+        // amount of data lost (given by audio_utils_fifo_reader)
+        size_t   lost() const { return mLost; }
+
+        // iterator to beginning of readable segment of snapshot
+        // data between begin and end has valid entries
+        EntryIterator begin() const { return mBegin; }
+
+        // iterator to end of readable segment of snapshot
+        EntryIterator end() const { return mEnd; }
+
+    private:
+        friend class Reader;
+        uint8_t * const       mData{};
+        size_t                mLost{0};
+        EntryIterator mBegin;
+        EntryIterator mEnd;
+    };
+
     class Reader : public RefBase {
     public:
-        // A snapshot of a readers buffer
-        // This is raw data. No analysis has been done on it
-        class Snapshot {
-        public:
-            Snapshot() : mData(NULL), mLost(0) {}
-
-            Snapshot(size_t bufferSize) : mData(new uint8_t[bufferSize]) {}
-
-            ~Snapshot() { delete[] mData; }
-
-            // copy of the buffer
-            uint8_t *data() const { return mData; }
-
-            // amount of data lost (given by audio_utils_fifo_reader)
-            size_t   lost() const { return mLost; }
-
-            // iterator to beginning of readable segment of snapshot
-            // data between begin and end has valid entries
-            EntryIterator begin() { return mBegin; }
-
-            // iterator to end of readable segment of snapshot
-            EntryIterator end() { return mEnd; }
-
-        private:
-            friend class Reader;
-            uint8_t              *mData;
-            size_t                mLost;
-            EntryIterator mBegin;
-            EntryIterator mEnd;
-        };
-
         // Input parameter 'size' is the desired size of the timeline in byte units.
         // The size of the shared memory must be at least Timeline::sharedSize(size).
         Reader(const void *shared, size_t size, const std::string &name);
         Reader(const sp<IMemory>& iMemory, size_t size, const std::string &name);
-
         virtual ~Reader();
 
         // get snapshot of readers fifo buffer, effectively consuming the buffer
         std::unique_ptr<Snapshot> getSnapshot();
-        // dump a particular snapshot of the reader
-        void dump(int fd, size_t indent, Snapshot &snap);
-        // dump the current content of the reader's buffer (call getSnapshot() and previous dump())
-        void dump(int fd, size_t indent = 0);
-
         bool     isIMemory(const sp<IMemory>& iMemory) const;
-
         const std::string &name() const { return mName; }
 
-    protected:
-        // print a summary of the performance to the console
-        void    dumpLine(const String8 *timestamp, String8 *body);
-        EntryIterator   handleFormat(const FormatEntry &fmtEntry,
-                                     String8 *timestamp,
-                                     String8 *body);
-        int mFd;                // file descriptor
-        int mIndent;            // indentation level
-        int mLost;              // bytes of data lost before buffer was read
-        const std::string mName;      // name of reader (actually name of writer)
-        static constexpr int kMaxObtainTries = 3;
-
     private:
+        static constexpr int kMaxObtainTries = 3;
+        // startingTypes and endingTypes are used to check for log corruption.
         static const std::unordered_set<Event> startingTypes;
         static const std::unordered_set<Event> endingTypes;
-
         // declared as const because audio_utils_fifo() constructor
         sp<IMemory> mIMemory;       // ref-counted version, assigned only in constructor
 
+        const std::string mName;            // name of reader (actually name of writer)
         /*const*/ Shared* const mShared;    // raw pointer to shared memory, actually const but not
         audio_utils_fifo * const mFifo;                 // FIFO itself,
-        // non-NULL unless constructor fails
+                                                        // non-NULL unless constructor fails
         audio_utils_fifo_reader * const mFifoReader;    // used to read from FIFO,
-        // non-NULL unless constructor fails
+                                                        // non-NULL unless constructor fails
 
         // Searches for the last entry of type <type> in the range [front, back)
         // back has to be entry-aligned. Returns nullptr if none enconuntered.
         static const uint8_t *findLastEntryOfTypes(const uint8_t *front, const uint8_t *back,
                                                    const std::unordered_set<Event> &types);
+    };
 
-        // dummy method for handling absent author entry
-        virtual void handleAuthor(const AbstractEntry& /*fmtEntry*/, String8* /*body*/) {}
+    class DumpReader : public Reader {
+    public:
+        DumpReader(const void *shared, size_t size, const std::string &name)
+            : Reader(shared, size, name) {}
+        DumpReader(const sp<IMemory>& iMemory, size_t size, const std::string &name)
+            : Reader(iMemory, size, name) {}
+        void dump(int fd, size_t indent = 0);
+    private:
+        void handleAuthor(const AbstractEntry& fmtEntry __unused, String8* body __unused) {}
+        EntryIterator handleFormat(const FormatEntry &fmtEntry, String8 *timestamp, String8 *body);
+
+        static void    appendInt(String8 *body, const void *data);
+        static void    appendFloat(String8 *body, const void *data);
+        static void    appendPID(String8 *body, const void *data, size_t length);
+        static void    appendTimestamp(String8 *body, const void *data);
+        //static size_t  fmtEntryLength(const uint8_t *data);   // TODO Eric remove if not used
+        static String8 bufferDump(const uint8_t *buffer, size_t size);
+        static String8 bufferDump(const EntryIterator &it);
     };
 
     // ---------------------------------------------------------------------------
@@ -542,7 +532,7 @@
 
         void dump(int fd, int indent = 0);
         // process a particular snapshot of the reader
-        void getAndProcessSnapshot(Snapshot & snap);
+        void getAndProcessSnapshot(Snapshot &snap, int author);
         // call getSnapshot of the content of the reader's buffer and process the data
         void getAndProcessSnapshot();
 
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 3370df1..c0e65e8 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -528,6 +528,18 @@
 
     ColorConverter converter((OMX_COLOR_FORMATTYPE)srcFormat, dstFormat());
 
+    uint32_t standard, range, transfer;
+    if (!outputFormat->findInt32("color-standard", (int32_t*)&standard)) {
+        standard = 0;
+    }
+    if (!outputFormat->findInt32("color-range", (int32_t*)&range)) {
+        range = 0;
+    }
+    if (!outputFormat->findInt32("color-transfer", (int32_t*)&transfer)) {
+        transfer = 0;
+    }
+    converter.setSrcColorSpace(standard, range, transfer);
+
     if (converter.isValid()) {
         converter.convert(
                 (const uint8_t *)videoFrameBuffer->data(),
@@ -699,6 +711,18 @@
 
     ColorConverter converter((OMX_COLOR_FORMATTYPE)srcFormat, dstFormat());
 
+    uint32_t standard, range, transfer;
+    if (!outputFormat->findInt32("color-standard", (int32_t*)&standard)) {
+        standard = 0;
+    }
+    if (!outputFormat->findInt32("color-range", (int32_t*)&range)) {
+        range = 0;
+    }
+    if (!outputFormat->findInt32("color-transfer", (int32_t*)&transfer)) {
+        transfer = 0;
+    }
+    converter.setSrcColorSpace(standard, range, transfer);
+
     int32_t dstLeft, dstTop, dstRight, dstBottom;
     dstLeft = mTilesDecoded % mGridCols * width;
     dstTop = mTilesDecoded / mGridCols * height;
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 2d4bd39..7578b1e 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -74,25 +74,26 @@
     source->DrmInitialization(nullptr /* mime */);
 
     void *meta = nullptr;
-    MediaExtractor::CreatorFunc creator = NULL;
-    MediaExtractor::FreeMetaFunc freeMeta = nullptr;
+    CreatorFunc creator = NULL;
+    FreeMetaFunc freeMeta = nullptr;
     float confidence;
     sp<ExtractorPlugin> plugin;
-    creator = sniff(source.get(), &confidence, &meta, &freeMeta, plugin);
+    creator = sniff(source, &confidence, &meta, &freeMeta, plugin);
     if (!creator) {
         ALOGV("FAILED to autodetect media content.");
         return NULL;
     }
 
-    MediaExtractor *ret = creator(source.get(), meta);
+    CMediaExtractor *ret = creator(source->wrap(), meta);
     if (meta != nullptr && freeMeta != nullptr) {
         freeMeta(meta);
     }
 
+    MediaExtractor *ex = ret != nullptr ? new MediaExtractorCUnwrapper(ret) : nullptr;
     ALOGV("Created an extractor '%s' with confidence %.2f",
-         ret != nullptr ? ret->name() : "<null>", confidence);
+         ex != nullptr ? ex->name() : "<null>", confidence);
 
-    return CreateIMediaExtractorFromMediaExtractor(ret, source, plugin);
+    return CreateIMediaExtractorFromMediaExtractor(ex, source, plugin);
 }
 
 //static
@@ -103,14 +104,14 @@
 }
 
 struct ExtractorPlugin : public RefBase {
-    MediaExtractor::ExtractorDef def;
+    ExtractorDef def;
     void *libHandle;
     String8 libPath;
     String8 uuidString;
 
-    ExtractorPlugin(MediaExtractor::ExtractorDef definition, void *handle, String8 &path)
+    ExtractorPlugin(ExtractorDef definition, void *handle, String8 &path)
         : def(definition), libHandle(handle), libPath(path) {
-        for (size_t i = 0; i < sizeof MediaExtractor::ExtractorDef::extractor_uuid; i++) {
+        for (size_t i = 0; i < sizeof ExtractorDef::extractor_uuid; i++) {
             uuidString.appendFormat("%02x", def.extractor_uuid.b[i]);
         }
     }
@@ -127,9 +128,9 @@
 bool MediaExtractorFactory::gPluginsRegistered = false;
 
 // static
-MediaExtractor::CreatorFunc MediaExtractorFactory::sniff(
-        DataSourceBase *source, float *confidence, void **meta,
-        MediaExtractor::FreeMetaFunc *freeMeta, sp<ExtractorPlugin> &plugin) {
+CreatorFunc MediaExtractorFactory::sniff(
+        const sp<DataSource> &source, float *confidence, void **meta,
+        FreeMetaFunc *freeMeta, sp<ExtractorPlugin> &plugin) {
     *confidence = 0.0f;
     *meta = nullptr;
 
@@ -142,14 +143,15 @@
         plugins = gPlugins;
     }
 
-    MediaExtractor::CreatorFunc curCreator = NULL;
-    MediaExtractor::CreatorFunc bestCreator = NULL;
+    CreatorFunc curCreator = NULL;
+    CreatorFunc bestCreator = NULL;
     for (auto it = plugins->begin(); it != plugins->end(); ++it) {
         ALOGV("sniffing %s", (*it)->def.extractor_name);
         float newConfidence;
         void *newMeta = nullptr;
-        MediaExtractor::FreeMetaFunc newFreeMeta = nullptr;
-        if ((curCreator = (*it)->def.sniff(source, &newConfidence, &newMeta, &newFreeMeta))) {
+        FreeMetaFunc newFreeMeta = nullptr;
+        if ((curCreator = (*it)->def.sniff(
+                        source->wrap(), &newConfidence, &newMeta, &newFreeMeta))) {
             if (newConfidence > *confidence) {
                 *confidence = newConfidence;
                 if (*meta != nullptr && *freeMeta != nullptr) {
@@ -175,7 +177,7 @@
         std::list<sp<ExtractorPlugin>> &pluginList) {
     // sanity check check struct version, uuid, name
     if (plugin->def.def_version == 0
-            || plugin->def.def_version > MediaExtractor::EXTRACTORDEF_VERSION) {
+            || plugin->def.def_version > EXTRACTORDEF_VERSION) {
         ALOGE("don't understand extractor format %u, ignoring.", plugin->def.def_version);
         return;
     }
@@ -236,8 +238,8 @@
                 // within the apk instead of system libraries already loaded.
                 void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
                 if (libHandle) {
-                    MediaExtractor::GetExtractorDef getDef =
-                        (MediaExtractor::GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
+                    GetExtractorDef getDef =
+                        (GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
                     if (getDef) {
                         ALOGV("registering sniffer for %s", libPath.string());
                         RegisterExtractor(
@@ -271,8 +273,8 @@
             String8 libPath = String8(libDirPath) + "/" + libEntry->d_name;
             void *libHandle = dlopen(libPath.string(), RTLD_NOW | RTLD_LOCAL);
             if (libHandle) {
-                MediaExtractor::GetExtractorDef getDef =
-                    (MediaExtractor::GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
+                GetExtractorDef getDef =
+                    (GetExtractorDef) dlsym(libHandle, "GETEXTRACTORDEF");
                 if (getDef) {
                     ALOGV("registering sniffer for %s", libPath.string());
                     RegisterExtractor(
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
index 26bc25c..df6cd03 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_framedecoder.cpp
@@ -299,7 +299,11 @@
         }
 
 
-        bytes_to_discard = pVars->frame_start - pVars->sideInfo.main_data_begin - main_data_end;
+        // force signed computation; buffer sizes and offsets are all going to be
+        // well within the constraints of 32-bit signed math.
+        bytes_to_discard = pVars->frame_start
+                           - ((int32)pVars->sideInfo.main_data_begin)
+                           - ((int32)main_data_end);
 
 
         if (main_data_end > BUFSIZE)   /* check overflow on the buffer */
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
index 7eaa860..e55c2e7 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
@@ -154,7 +154,7 @@
                 tmp = getbits_crc(inputStream, 22, crc, info->error_protection);
 
                 si->ch[ch].gran[gr].big_values            = (tmp << 10) >> 23;   /* 9 */
-                si->ch[ch].gran[gr].global_gain           = ((tmp << 19) >> 24) - 210;   /* 8 */
+                si->ch[ch].gran[gr].global_gain        = (int32)((tmp << 19) >> 24) - 210; /* 8 */
                 si->ch[ch].gran[gr].scalefac_compress     = (tmp << 27) >> 28;   /* 4 */
                 si->ch[ch].gran[gr].window_switching_flag = tmp & 1;         /* 1 */
 
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
index 10edfc3..4338c43 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_stereo_proc.cpp
@@ -178,6 +178,10 @@
 ; FUNCTION CODE
 ----------------------------------------------------------------------------*/
 
+#if __has_attribute(no_sanitize)
+// deliberately playing near overflow points of int32
+__attribute__((no_sanitize("integer")))
+#endif
 void pvmp3_st_mid_side(int32 xr[SUBBANDS_NUMBER*FILTERBANK_BANDS],
                        int32 xl[SUBBANDS_NUMBER*FILTERBANK_BANDS],
                        int32 Start,
diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp
index c46a40f..862cc63 100644
--- a/media/libstagefright/colorconversion/ColorConverter.cpp
+++ b/media/libstagefright/colorconversion/ColorConverter.cpp
@@ -20,10 +20,12 @@
 
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/ColorUtils.h>
 #include <media/stagefright/ColorConverter.h>
 #include <media/stagefright/MediaErrors.h>
 
 #include "libyuv/convert_from.h"
+#include "libyuv/convert_argb.h"
 #include "libyuv/video_common.h"
 #include <functional>
 #include <sys/time.h>
@@ -44,10 +46,28 @@
 
 namespace android {
 
+static bool isRGB(OMX_COLOR_FORMATTYPE colorFormat) {
+    return colorFormat == OMX_COLOR_Format16bitRGB565
+            || colorFormat == OMX_COLOR_Format32BitRGBA8888
+            || colorFormat == OMX_COLOR_Format32bitBGRA8888;
+}
+
+bool ColorConverter::ColorSpace::isBt709() {
+    return (mStandard == ColorUtils::kColorStandardBT709);
+}
+
+
+bool ColorConverter::ColorSpace::isJpeg() {
+    return ((mStandard == ColorUtils::kColorStandardBT601_625)
+            || (mStandard == ColorUtils::kColorStandardBT601_525))
+            && (mRange == ColorUtils::kColorRangeFull);
+}
+
 ColorConverter::ColorConverter(
         OMX_COLOR_FORMATTYPE from, OMX_COLOR_FORMATTYPE to)
     : mSrcFormat(from),
       mDstFormat(to),
+      mSrcColorSpace({0, 0, 0}),
       mClip(NULL) {
 }
 
@@ -80,9 +100,18 @@
 }
 
 bool ColorConverter::isDstRGB() const {
-    return mDstFormat == OMX_COLOR_Format16bitRGB565
-            || mDstFormat == OMX_COLOR_Format32BitRGBA8888
-            || mDstFormat == OMX_COLOR_Format32bitBGRA8888;
+    return isRGB(mDstFormat);
+}
+
+void ColorConverter::setSrcColorSpace(
+        uint32_t standard, uint32_t range, uint32_t transfer) {
+    if (isRGB(mSrcFormat)) {
+        ALOGW("Can't set color space on RGB source");
+        return;
+    }
+    mSrcColorSpace.mStandard = standard;
+    mSrcColorSpace.mRange = range;
+    mSrcColorSpace.mTransfer = transfer;
 }
 
 /*
@@ -281,6 +310,13 @@
     return OK;
 }
 
+#define DECLARE_YUV2RGBFUNC(func, rgb) int (*func)(     \
+        const uint8*, int, const uint8*, int,           \
+        const uint8*, int, uint8*, int, int, int)       \
+        = mSrcColorSpace.isBt709() ? libyuv::H420To##rgb \
+        : mSrcColorSpace.isJpeg() ? libyuv::J420To##rgb  \
+        : libyuv::I420To##rgb
+
 status_t ColorConverter::convertYUV420PlanarUseLibYUV(
         const BitmapParams &src, const BitmapParams &dst) {
     uint8_t *dst_ptr = (uint8_t *)dst.mBits
@@ -298,19 +334,28 @@
 
     switch (mDstFormat) {
     case OMX_COLOR_Format16bitRGB565:
-        libyuv::I420ToRGB565(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
+    {
+        DECLARE_YUV2RGBFUNC(func, RGB565);
+        (*func)(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
                 (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight());
         break;
+    }
 
     case OMX_COLOR_Format32BitRGBA8888:
-        libyuv::ConvertFromI420(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
-                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight(), libyuv::FOURCC_ABGR);
+    {
+        DECLARE_YUV2RGBFUNC(func, ABGR);
+        (*func)(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
+                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight());
         break;
+    }
 
     case OMX_COLOR_Format32bitBGRA8888:
-        libyuv::ConvertFromI420(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
-                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight(), libyuv::FOURCC_ARGB);
+    {
+        DECLARE_YUV2RGBFUNC(func, ARGB);
+        (*func)(src_y, src.mStride, src_u, src.mStride / 2, src_v, src.mStride / 2,
+                (uint8 *)dst_ptr, dst.mStride, src.cropWidth(), src.cropHeight());
         break;
+    }
 
     default:
         return ERROR_UNSUPPORTED;
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index a0a62f4..b489183 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -21,6 +21,8 @@
 #include "../include/ID3.h"
 
 #include <media/DataSource.h>
+#include <media/MediaExtractorPluginApi.h>
+#include <media/MediaExtractorPluginHelper.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ByteUtils.h>
 #include <utils/String8.h>
@@ -56,6 +58,55 @@
     DISALLOW_EVIL_CONSTRUCTORS(MemorySource);
 };
 
+class DataSourceUnwrapper : public DataSourceBase {
+
+public:
+    explicit DataSourceUnwrapper(DataSourceHelper *sourcehelper) {
+        mSource = sourcehelper;
+    }
+    virtual status_t initCheck() const { return OK; }
+
+    // Returns the number of bytes read, or -1 on failure. It's not an error if
+    // this returns zero; it just means the given offset is equal to, or
+    // beyond, the end of the source.
+    virtual ssize_t readAt(off64_t offset, void *data, size_t size) {
+        return mSource->readAt(offset, data, size);
+    }
+
+    // May return ERROR_UNSUPPORTED.
+    virtual status_t getSize(off64_t *size) {
+        return mSource->getSize(size);
+    }
+
+    virtual bool getUri(char * /*uriString*/, size_t /*bufferSize*/) {
+        return false;
+    }
+
+    virtual uint32_t flags() {
+        return 0;
+    }
+
+    virtual void close() {};
+private:
+    DataSourceHelper *mSource;
+};
+
+
+ID3::ID3(DataSourceHelper *sourcehelper, bool ignoreV1, off64_t offset)
+    : mIsValid(false),
+      mData(NULL),
+      mSize(0),
+      mFirstFrameOffset(0),
+      mVersion(ID3_UNKNOWN),
+      mRawSize(0) {
+    DataSourceUnwrapper source(sourcehelper);
+    mIsValid = parseV2(&source, offset);
+
+    if (!mIsValid && !ignoreV1) {
+        mIsValid = parseV1(&source);
+    }
+}
+
 ID3::ID3(DataSourceBase *source, bool ignoreV1, off64_t offset)
     : mIsValid(false),
       mData(NULL),
diff --git a/media/libstagefright/include/ID3.h b/media/libstagefright/include/ID3.h
index 7c2391e..5e433ea 100644
--- a/media/libstagefright/include/ID3.h
+++ b/media/libstagefright/include/ID3.h
@@ -24,6 +24,7 @@
 
 class DataSourceBase;
 class String8;
+class DataSourceHelper;
 
 struct ID3 {
     enum Version {
@@ -35,6 +36,7 @@
         ID3_V2_4,
     };
 
+    explicit ID3(DataSourceHelper *source, bool ignoreV1 = false, off64_t offset = 0);
     explicit ID3(DataSourceBase *source, bool ignoreV1 = false, off64_t offset = 0);
     ID3(const uint8_t *data, size_t size, bool ignoreV1 = false);
     ~ID3();
diff --git a/media/libstagefright/include/media/stagefright/ColorConverter.h b/media/libstagefright/include/media/stagefright/ColorConverter.h
index 2b8c7c8..6d4c1bf 100644
--- a/media/libstagefright/include/media/stagefright/ColorConverter.h
+++ b/media/libstagefright/include/media/stagefright/ColorConverter.h
@@ -35,6 +35,8 @@
 
     bool isDstRGB() const;
 
+    void setSrcColorSpace(uint32_t standard, uint32_t range, uint32_t transfer);
+
     status_t convert(
             const void *srcBits,
             size_t srcWidth, size_t srcHeight, size_t srcStride,
@@ -46,6 +48,15 @@
             size_t dstCropRight, size_t dstCropBottom);
 
 private:
+    struct ColorSpace {
+        uint32_t mStandard;
+        uint32_t mRange;
+        uint32_t mTransfer;
+
+        bool isBt709();
+        bool isJpeg();
+    };
+
     struct BitmapParams {
         BitmapParams(
                 void *bits,
@@ -65,6 +76,7 @@
     };
 
     OMX_COLOR_FORMATTYPE mSrcFormat, mDstFormat;
+    ColorSpace mSrcColorSpace;
     uint8_t *mClip;
 
     uint8_t *initClip();
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index d5f4b35..4ee5556 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -49,8 +49,8 @@
     static void RegisterExtractor(
             const sp<ExtractorPlugin> &plugin, std::list<sp<ExtractorPlugin>> &pluginList);
 
-    static MediaExtractor::CreatorFunc sniff(DataSourceBase *source,
-            float *confidence, void **meta, MediaExtractor::FreeMetaFunc *freeMeta,
+    static CreatorFunc sniff(const sp<DataSource> &source,
+            float *confidence, void **meta, FreeMetaFunc *freeMeta,
             sp<ExtractorPlugin> &plugin);
 
     static void UpdateExtractors(const char *newUpdateApkPath);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 43566b7..ed2b3c0 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -66,7 +66,6 @@
 #include <media/MemoryLeakTrackUtil.h>
 #include <media/nbaio/Pipe.h>
 #include <media/nbaio/PipeReader.h>
-#include <media/AudioParameter.h>
 #include <mediautils/BatteryNotifier.h>
 #include <mediautils/ServiceUtilities.h>
 #include <private/android_filesystem_config.h>
@@ -517,6 +516,15 @@
 
         mPatchPanel.dump(fd);
 
+        // dump external setParameters
+        auto dumpLogger = [fd](SimpleLog& logger, const char* name) {
+            dprintf(fd, "\n%s setParameters:\n", name);
+            logger.dump(fd, "    " /* prefix */);
+        };
+        dumpLogger(mRejectedSetParameterLog, "Rejected");
+        dumpLogger(mAppSetParameterLog, "App");
+        dumpLogger(mSystemSetParameterLog, "System");
+
         BUFLOG_RESET;
 
         if (locked) {
@@ -1229,16 +1237,33 @@
 
     AudioParameter param = AudioParameter(keyValuePairs);
     String8 value;
+    AudioParameter rejectedParam;
     for (auto& key : kReservedParameters) {
         if (param.get(key, value) == NO_ERROR) {
-            ALOGW("%s: filtering key %s value %s from uid %d",
-                  __func__, key.string(), value.string(), callingUid);
+            rejectedParam.add(key, value);
             param.remove(key);
         }
     }
+    logFilteredParameters(param.size() + rejectedParam.size(), keyValuePairs,
+                          rejectedParam.size(), rejectedParam.toString(), callingUid);
     keyValuePairs = param.toString();
 }
 
+void AudioFlinger::logFilteredParameters(size_t originalKVPSize, const String8& originalKVPs,
+                                         size_t rejectedKVPSize, const String8& rejectedKVPs,
+                                         uid_t callingUid) {
+    auto prefix = String8::format("UID %5d", callingUid);
+    auto suffix = String8::format("%zu KVP received: %s", originalKVPSize, originalKVPs.c_str());
+    if (rejectedKVPSize != 0) {
+        auto error = String8::format("%zu KVP rejected: %s", rejectedKVPSize, rejectedKVPs.c_str());
+        ALOGW("%s: %s, %s, %s", __func__, prefix.c_str(), error.c_str(), suffix.c_str());
+        mRejectedSetParameterLog.log("%s, %s, %s", prefix.c_str(), error.c_str(), suffix.c_str());
+    } else {
+        auto& logger = (isServiceUid(callingUid) ? mSystemSetParameterLog : mAppSetParameterLog);
+        logger.log("%s, %s", prefix.c_str(), suffix.c_str());
+    }
+}
+
 status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs)
 {
     ALOGV("setParameters(): io %d, keyvalue %s, calling pid %d calling uid %d",
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 2d2da3e..9c36479 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -812,6 +812,9 @@
     status_t    checkStreamType(audio_stream_type_t stream) const;
 
     void        filterReservedParameters(String8& keyValuePairs, uid_t callingUid);
+    void        logFilteredParameters(size_t originalKVPSize, const String8& originalKVPs,
+                                      size_t rejectedKVPSize, const String8& rejectedKVPs,
+                                      uid_t callingUid);
 
 public:
     // These methods read variables atomically without mLock,
@@ -832,7 +835,11 @@
     PatchPanel mPatchPanel;
     sp<EffectsFactoryHalInterface> mEffectsFactoryHal;
 
-    bool        mSystemReady;
+    bool       mSystemReady;
+
+    SimpleLog  mRejectedSetParameterLog;
+    SimpleLog  mAppSetParameterLog;
+    SimpleLog  mSystemSetParameterLog;
 };
 
 #undef INCLUDING_FROM_AUDIOFLINGER_H
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 2858aad..b3d564a 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -318,6 +318,74 @@
     return status;
 }
 
+status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
+                                                    const String16& opPackageName,
+                                                    const effect_uuid_t *uuid,
+                                                    int32_t priority,
+                                                    audio_source_t source,
+                                                    audio_unique_id_t* id)
+{
+    if (uuid == NULL || type == NULL) {
+        ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
+        return BAD_VALUE;
+    }
+
+    // HOTWORD and FM_TUNER are two special case sources > MAX.
+    if (source < AUDIO_SOURCE_DEFAULT ||
+            (source > AUDIO_SOURCE_MAX &&
+             source != AUDIO_SOURCE_HOTWORD &&
+             source != AUDIO_SOURCE_FM_TUNER)) {
+        ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
+        return BAD_VALUE;
+    }
+
+    // Check that |uuid| or |type| corresponds to an effect on the system.
+    effect_descriptor_t descriptor = {};
+    status_t res = AudioEffect::getEffectDescriptor(
+            uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
+    if (res != OK) {
+        ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
+        return res;
+    }
+
+    // Only pre-processing effects can be added dynamically as source defaults.
+    if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
+        ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
+              "as a source default effect.");
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mLock);
+
+    // Find the EffectDescVector for the given source type, or create a new one if necessary.
+    ssize_t index = mInputSources.indexOfKey(source);
+    EffectDescVector *desc = NULL;
+    if (index < 0) {
+        // No effects for this source type yet.
+        desc = new EffectDescVector();
+        mInputSources.add(source, desc);
+    } else {
+        desc = mInputSources.valueAt(index);
+    }
+
+    // Create a new effect and add it to the vector.
+    res = AudioEffect::newEffectUniqueId(id);
+    if (res != OK) {
+        ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
+        return res;
+    }
+    EffectDesc *effect = new EffectDesc(
+            descriptor.name, *type, opPackageName, *uuid, priority, *id);
+    desc->mEffects.add(effect);
+    // TODO(b/71813697): Support setting params as well.
+
+    // TODO(b/71814300): Retroactively attach to any existing sources of the given type.
+    // This requires tracking the source type of each session id in addition to what is
+    // already being tracked.
+
+    return NO_ERROR;
+}
+
 status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
                                                     const String16& opPackageName,
                                                     const effect_uuid_t *uuid,
@@ -384,6 +452,37 @@
     return NO_ERROR;
 }
 
+status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
+{
+    if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
+        // ALLOCATE is not a unique identifier, but rather a reserved value indicating
+        // a real id has not been assigned. For default effects, this value is only used
+        // by system-owned defaults from the loaded config, which cannot be removed.
+        return BAD_VALUE;
+    }
+
+    Mutex::Autolock _l(mLock);
+
+    // Check each source type.
+    size_t numSources = mInputSources.size();
+    for (size_t i = 0; i < numSources; ++i) {
+        // Check each effect for each source.
+        EffectDescVector* descVector = mInputSources[i];
+        for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
+            if ((*desc)->mId == id) {
+                // Found it!
+                // TODO(b/71814300): Remove from any sources the effect was attached to.
+                descVector->mEffects.erase(desc);
+                // Handles are unique; there can only be one match, so return early.
+                return NO_ERROR;
+            }
+        }
+    }
+
+    // Effect wasn't found, so it's been trivially removed successfully.
+    return NO_ERROR;
+}
+
 status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
 {
     if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 69367b1..6ad01f7 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -81,7 +81,15 @@
                              audio_stream_type_t stream,
                              audio_session_t audioSession);
 
-    // Add the effect to the list of default effects for streams of type |stream|.
+    // Add the effect to the list of default effects for sources of type |source|.
+    status_t addSourceDefaultEffect(const effect_uuid_t *type,
+                                    const String16& opPackageName,
+                                    const effect_uuid_t *uuid,
+                                    int32_t priority,
+                                    audio_source_t source,
+                                    audio_unique_id_t* id);
+
+    // Add the effect to the list of default effects for streams of a given usage.
     status_t addStreamDefaultEffect(const effect_uuid_t *type,
                                     const String16& opPackageName,
                                     const effect_uuid_t *uuid,
@@ -89,6 +97,9 @@
                                     audio_usage_t usage,
                                     audio_unique_id_t* id);
 
+    // Remove the default source effect from wherever it's attached.
+    status_t removeSourceDefaultEffect(audio_unique_id_t id);
+
     // Remove the default stream effect from wherever it's attached.
     status_t removeStreamDefaultEffect(audio_unique_id_t id);
 
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 3439c9b..02ab07f 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -829,27 +829,55 @@
     return mAudioPolicyManager->isSourceActive(source);
 }
 
-status_t AudioPolicyService::queryDefaultPreProcessing(audio_session_t audioSession,
-                                                       effect_descriptor_t *descriptors,
-                                                       uint32_t *count)
+status_t AudioPolicyService::getAudioPolicyEffects(sp<AudioPolicyEffects>& audioPolicyEffects)
 {
     if (mAudioPolicyManager == NULL) {
-        *count = 0;
         return NO_INIT;
     }
-    sp<AudioPolicyEffects>audioPolicyEffects;
     {
         Mutex::Autolock _l(mLock);
         audioPolicyEffects = mAudioPolicyEffects;
     }
     if (audioPolicyEffects == 0) {
-        *count = 0;
         return NO_INIT;
     }
+
+    return OK;
+}
+
+status_t AudioPolicyService::queryDefaultPreProcessing(audio_session_t audioSession,
+                                                       effect_descriptor_t *descriptors,
+                                                       uint32_t *count)
+{
+    sp<AudioPolicyEffects>audioPolicyEffects;
+    status_t status = getAudioPolicyEffects(audioPolicyEffects);
+    if (status != OK) {
+        *count = 0;
+        return status;
+    }
     return audioPolicyEffects->queryDefaultInputEffects(
             (audio_session_t)audioSession, descriptors, count);
 }
 
+status_t AudioPolicyService::addSourceDefaultEffect(const effect_uuid_t *type,
+                                                    const String16& opPackageName,
+                                                    const effect_uuid_t *uuid,
+                                                    int32_t priority,
+                                                    audio_source_t source,
+                                                    audio_unique_id_t* id)
+{
+    sp<AudioPolicyEffects>audioPolicyEffects;
+    status_t status = getAudioPolicyEffects(audioPolicyEffects);
+    if (status != OK) {
+        return status;
+    }
+    if (!modifyDefaultAudioEffectsAllowed()) {
+        return PERMISSION_DENIED;
+    }
+    return audioPolicyEffects->addSourceDefaultEffect(
+            type, opPackageName, uuid, priority, source, id);
+}
+
 status_t AudioPolicyService::addStreamDefaultEffect(const effect_uuid_t *type,
                                                     const String16& opPackageName,
                                                     const effect_uuid_t *uuid,
@@ -857,39 +885,40 @@
                                                     audio_usage_t usage,
                                                     audio_unique_id_t* id)
 {
-    if (mAudioPolicyManager == NULL) {
-        return NO_INIT;
+    sp<AudioPolicyEffects>audioPolicyEffects;
+    status_t status = getAudioPolicyEffects(audioPolicyEffects);
+    if (status != OK) {
+        return status;
     }
     if (!modifyDefaultAudioEffectsAllowed()) {
         return PERMISSION_DENIED;
     }
-    sp<AudioPolicyEffects>audioPolicyEffects;
-    {
-        Mutex::Autolock _l(mLock);
-        audioPolicyEffects = mAudioPolicyEffects;
-    }
-    if (audioPolicyEffects == 0) {
-        return NO_INIT;
-    }
     return audioPolicyEffects->addStreamDefaultEffect(
             type, opPackageName, uuid, priority, usage, id);
 }
 
-status_t AudioPolicyService::removeStreamDefaultEffect(audio_unique_id_t id)
+status_t AudioPolicyService::removeSourceDefaultEffect(audio_unique_id_t id)
 {
-    if (mAudioPolicyManager == NULL) {
-        return NO_INIT;
+    sp<AudioPolicyEffects>audioPolicyEffects;
+    status_t status = getAudioPolicyEffects(audioPolicyEffects);
+    if (status != OK) {
+        return status;
     }
     if (!modifyDefaultAudioEffectsAllowed()) {
         return PERMISSION_DENIED;
     }
+    return audioPolicyEffects->removeSourceDefaultEffect(id);
+}
+
+status_t AudioPolicyService::removeStreamDefaultEffect(audio_unique_id_t id)
+{
     sp<AudioPolicyEffects>audioPolicyEffects;
-    {
-        Mutex::Autolock _l(mLock);
-        audioPolicyEffects = mAudioPolicyEffects;
+    status_t status = getAudioPolicyEffects(audioPolicyEffects);
+    if (status != OK) {
+        return status;
     }
-    if (audioPolicyEffects == 0) {
-        return NO_INIT;
+    if (!modifyDefaultAudioEffectsAllowed()) {
+        return PERMISSION_DENIED;
     }
     return audioPolicyEffects->removeStreamDefaultEffect(id);
 }
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 44c0347..6c55647 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -126,12 +126,19 @@
     virtual status_t queryDefaultPreProcessing(audio_session_t audioSession,
                                               effect_descriptor_t *descriptors,
                                               uint32_t *count);
+    virtual status_t addSourceDefaultEffect(const effect_uuid_t *type,
+                                            const String16& opPackageName,
+                                            const effect_uuid_t *uuid,
+                                            int32_t priority,
+                                            audio_source_t source,
+                                            audio_unique_id_t* id);
     virtual status_t addStreamDefaultEffect(const effect_uuid_t *type,
                                             const String16& opPackageName,
                                             const effect_uuid_t *uuid,
                                             int32_t priority,
                                             audio_usage_t usage,
                                             audio_unique_id_t* id);
+    virtual status_t removeSourceDefaultEffect(audio_unique_id_t id);
     virtual status_t removeStreamDefaultEffect(audio_unique_id_t id);
 
     virtual     status_t    onTransact(
@@ -259,6 +266,8 @@
 
     std::string getDeviceTypeStrForPortId(audio_port_handle_t portId);
 
+    status_t getAudioPolicyEffects(sp<AudioPolicyEffects>& audioPolicyEffects);
+
     // If recording we need to make sure the UID is allowed to do that. If the UID is idle
     // then it cannot record and gets buffers with zeros - silence. As soon as the UID
     // transitions to an active state we will start reporting buffers with data. This approach
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index b85dd51..f9240db 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2429,7 +2429,8 @@
     return isUidActiveLocked(uid, callingPackage);
 }
 
-static const int kPollUidActiveTimeoutMillis = 50;
+static const int64_t kPollUidActiveTimeoutTotalMillis = 300;
+static const int64_t kPollUidActiveTimeoutMillis = 50;
 
 bool CameraService::UidPolicy::isUidActiveLocked(uid_t uid, String16 callingPackage) {
     // Non-app UIDs are considered always active
@@ -2457,7 +2458,8 @@
             // activity being resumed. The proper fix is very risky, so we temporary add
             // some polling which should happen pretty rarely anyway as the race is hard
             // to hit.
-            active = am.isUidActive(uid, callingPackage);
+            active = mActiveUids.find(uid) != mActiveUids.end();
+            if (!active) active = am.isUidActive(uid, callingPackage);
             if (active) {
                 break;
             }
@@ -2465,11 +2467,15 @@
                 startTimeMillis = uptimeMillis();
             }
             int64_t ellapsedTimeMillis = uptimeMillis() - startTimeMillis;
-            int64_t remainingTimeMillis = kPollUidActiveTimeoutMillis - ellapsedTimeMillis;
+            int64_t remainingTimeMillis = kPollUidActiveTimeoutTotalMillis - ellapsedTimeMillis;
             if (remainingTimeMillis <= 0) {
                 break;
             }
+            remainingTimeMillis = std::min(kPollUidActiveTimeoutMillis, remainingTimeMillis);
+
+            mUidLock.unlock();
             usleep(remainingTimeMillis * 1000);
+            mUidLock.lock();
         } while (true);
 
         if (active) {
diff --git a/services/camera/libcameraservice/TEST_MAPPING b/services/camera/libcameraservice/TEST_MAPPING
new file mode 100644
index 0000000..6fdac68
--- /dev/null
+++ b/services/camera/libcameraservice/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+       "name": "cameraservice_test"
+    }
+  ]
+}
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index ef93d9a..0086c6c 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -163,7 +163,7 @@
         mTestCameraProvider = provider;
     }
 
-    std::string mLastRequestedServiceName;
+    std::vector<std::string> mLastRequestedServiceNames;
 
     virtual ~TestInteractionProxy() {}
 
@@ -177,7 +177,7 @@
 
     virtual sp<hardware::camera::provider::V2_4::ICameraProvider> getService(
             const std::string &serviceName) override {
-        mLastRequestedServiceName = serviceName;
+        mLastRequestedServiceNames.push_back(serviceName);
         return mTestCameraProvider;
     }
 
@@ -210,9 +210,18 @@
     res = providerManager->initialize(statusListener, &serviceProxy);
     ASSERT_EQ(res, OK) << "Unable to initialize provider manager";
 
-    hardware::hidl_string legacyInstanceName = "legacy/0";
-    ASSERT_EQ(serviceProxy.mLastRequestedServiceName, legacyInstanceName) <<
+    std::string legacyInstanceName = "legacy/0";
+    std::string externalInstanceName = "external/0";
+    bool gotLegacy = false;
+    bool gotExternal = false;
+    for (auto& serviceName : serviceProxy.mLastRequestedServiceNames) {
+        if (serviceName == legacyInstanceName) gotLegacy = true;
+        if (serviceName == externalInstanceName) gotExternal = true;
+    }
+    ASSERT_TRUE(gotLegacy) <<
             "Legacy instance not requested from service manager";
+    ASSERT_TRUE(gotExternal) <<
+            "External instance not requested from service manager";
 
     hardware::hidl_string testProviderFqInterfaceName =
             "android.hardware.camera.provider@2.4::ICameraProvider";
@@ -221,7 +230,7 @@
             testProviderFqInterfaceName,
             testProviderInstanceName, false);
 
-    ASSERT_EQ(serviceProxy.mLastRequestedServiceName, testProviderInstanceName) <<
+    ASSERT_EQ(serviceProxy.mLastRequestedServiceNames.back(), testProviderInstanceName) <<
             "Incorrect instance requested from service manager";
 }
 
@@ -255,7 +264,7 @@
             "android.hardware.camera.provider@2.4::ICameraProvider";
     serviceProxy.mManagerNotificationInterface->onRegistration(
             testProviderFqInterfaceName, testProviderInstanceName, false);
-    ASSERT_EQ(serviceProxy.mLastRequestedServiceName, testProviderInstanceName) <<
+    ASSERT_EQ(serviceProxy.mLastRequestedServiceNames.back(), testProviderInstanceName) <<
             "Incorrect instance requested from service manager";
 
     hardware::hidl_string sectionNameSecond = "SecondVendorTestSection";
@@ -273,7 +282,7 @@
     hardware::hidl_string testProviderSecondInstanceName = "test2/0";
     serviceProxy.mManagerNotificationInterface->onRegistration(
             testProviderFqInterfaceName, testProviderSecondInstanceName, false);
-    ASSERT_EQ(serviceProxy.mLastRequestedServiceName,
+    ASSERT_EQ(serviceProxy.mLastRequestedServiceNames.back(),
               testProviderSecondInstanceName) <<
             "Incorrect instance requested from service manager";
 
diff --git a/services/medialog/MediaLogService.cpp b/services/medialog/MediaLogService.cpp
index 095dd5c..b23832e 100644
--- a/services/medialog/MediaLogService.cpp
+++ b/services/medialog/MediaLogService.cpp
@@ -58,9 +58,10 @@
             shared->size() < NBLog::Timeline::sharedSize(size)) {
         return;
     }
-    sp<NBLog::Reader> reader(new NBLog::Reader(shared, size, name));
+    sp<NBLog::Reader> reader(new NBLog::Reader(shared, size, name)); // Reader handled by merger
+    sp<NBLog::DumpReader> dumpReader(new NBLog::DumpReader(shared, size, name)); // for dumpsys
     Mutex::Autolock _l(mLock);
-    mReaders.add(reader);
+    mDumpReaders.add(dumpReader);
     mMerger.addReader(reader);
 }
 
@@ -70,9 +71,10 @@
         return;
     }
     Mutex::Autolock _l(mLock);
-    for (size_t i = 0; i < mReaders.size(); ) {
-        if (mReaders[i]->isIMemory(shared)) {
-            mReaders.removeAt(i);
+    for (size_t i = 0; i < mDumpReaders.size(); ) {
+        if (mDumpReaders[i]->isIMemory(shared)) {
+            mDumpReaders.removeAt(i);
+            // TODO mMerger.removeReaders(shared)
         } else {
             i++;
         }
@@ -120,18 +122,18 @@
                 return NO_ERROR;
             }
 
-            for (auto reader : mReaders) {
+            for (const auto &dumpReader : mDumpReaders) {
                 if (fd >= 0) {
-                    dprintf(fd, "\n%s:\n", reader->name().c_str());
-                    reader->dump(fd, 0 /*indent*/);
+                    dprintf(fd, "\n%s:\n", dumpReader->name().c_str());
+                    dumpReader->dump(fd, 0 /*indent*/);
                 } else {
-                    ALOGI("%s:", reader->name().c_str());
+                    ALOGI("%s:", dumpReader->name().c_str());
                 }
             }
             mLock.unlock();
         }
     }
-    //mMergeReader.dump(fd);
+    mMergeReader.dump(fd);
     return NO_ERROR;
 }
 
diff --git a/services/medialog/MediaLogService.h b/services/medialog/MediaLogService.h
index 3763484..a1572f9 100644
--- a/services/medialog/MediaLogService.h
+++ b/services/medialog/MediaLogService.h
@@ -55,7 +55,7 @@
 
     Mutex               mLock;
 
-    Vector<sp<NBLog::Reader>> mReaders;   // protected by mLock
+    Vector<sp<NBLog::DumpReader>> mDumpReaders;   // protected by mLock
 
     // FIXME Need comments on all of these, especially about locking
     NBLog::Shared *mMergerShared;