Merge "Benchmark: Change library names to begin with libmediabenchmark"
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index a1ee904..9ba6ee1 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -1085,7 +1085,7 @@
         const char *filename = argv[k];
 
         sp<DataSource> dataSource =
-            DataSourceFactory::CreateFromURI(NULL /* httpService */, filename);
+            DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, filename);
 
         if (strncasecmp(filename, "sine:", 5) && dataSource == NULL) {
             fprintf(stderr, "Unable to create data source.\n");
diff --git a/cmds/stagefright/stream.cpp b/cmds/stagefright/stream.cpp
index 0634673..22e2ef3 100644
--- a/cmds/stagefright/stream.cpp
+++ b/cmds/stagefright/stream.cpp
@@ -164,7 +164,7 @@
     : mCurrentBufferIndex(-1),
       mCurrentBufferOffset(0) {
     sp<DataSource> dataSource =
-        DataSourceFactory::CreateFromURI(NULL /* httpService */, filename);
+        DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, filename);
 
     CHECK(dataSource != NULL);
 
diff --git a/media/codec2/components/cmds/codec2.cpp b/media/codec2/components/cmds/codec2.cpp
index e572a53..38eaf88 100644
--- a/media/codec2/components/cmds/codec2.cpp
+++ b/media/codec2/components/cmds/codec2.cpp
@@ -418,7 +418,7 @@
         const char *filename = argv[k];
 
         sp<DataSource> dataSource =
-            DataSourceFactory::CreateFromURI(nullptr /* httpService */, filename);
+            DataSourceFactory::getInstance()->CreateFromURI(nullptr /* httpService */, filename);
 
         if (strncasecmp(filename, "sine:", 5) && dataSource == nullptr) {
             fprintf(stderr, "Unable to create data source.\n");
diff --git a/media/libdatasource/Android.bp b/media/libdatasource/Android.bp
index dd8ef74..f191c21 100644
--- a/media/libdatasource/Android.bp
+++ b/media/libdatasource/Android.bp
@@ -2,8 +2,6 @@
     name: "libdatasource",
 
     srcs: [
-        "ClearFileSource.cpp",
-        "ClearMediaHTTP.cpp",
         "DataSourceFactory.cpp",
         "DataURISource.cpp",
         "FileSource.cpp",
@@ -31,7 +29,6 @@
     shared_libs: [
         "liblog",
         "libcutils",
-        "libdrmframework",
         "libutils",
         "libstagefright_foundation",
         "libdl",
diff --git a/media/libdatasource/ClearFileSource.cpp b/media/libdatasource/ClearFileSource.cpp
deleted file mode 100644
index afafa23..0000000
--- a/media/libdatasource/ClearFileSource.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "ClearFileSource"
-#include <utils/Log.h>
-
-#include <datasource/ClearFileSource.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/FoundationUtils.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-namespace android {
-
-ClearFileSource::ClearFileSource(const char *filename)
-    : mFd(-1),
-      mOffset(0),
-      mLength(-1),
-      mName("<null>") {
-
-    if (filename) {
-        mName = String8::format("FileSource(%s)", filename);
-    }
-    ALOGV("%s", filename);
-    mFd = open(filename, O_LARGEFILE | O_RDONLY);
-
-    if (mFd >= 0) {
-        mLength = lseek64(mFd, 0, SEEK_END);
-    } else {
-        ALOGE("Failed to open file '%s'. (%s)", filename, strerror(errno));
-    }
-}
-
-ClearFileSource::ClearFileSource(int fd, int64_t offset, int64_t length)
-    : mFd(fd),
-      mOffset(offset),
-      mLength(length),
-      mName("<null>") {
-    ALOGV("fd=%d (%s), offset=%lld, length=%lld",
-            fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
-
-    if (mOffset < 0) {
-        mOffset = 0;
-    }
-    if (mLength < 0) {
-        mLength = 0;
-    }
-    if (mLength > INT64_MAX - mOffset) {
-        mLength = INT64_MAX - mOffset;
-    }
-    struct stat s;
-    if (fstat(fd, &s) == 0) {
-        if (mOffset > s.st_size) {
-            mOffset = s.st_size;
-            mLength = 0;
-        }
-        if (mOffset + mLength > s.st_size) {
-            mLength = s.st_size - mOffset;
-        }
-    }
-    if (mOffset != offset || mLength != length) {
-        ALOGW("offset/length adjusted from %lld/%lld to %lld/%lld",
-                (long long) offset, (long long) length,
-                (long long) mOffset, (long long) mLength);
-    }
-
-    mName = String8::format(
-            "FileSource(fd(%s), %lld, %lld)",
-            nameForFd(fd).c_str(),
-            (long long) mOffset,
-            (long long) mLength);
-
-}
-
-ClearFileSource::~ClearFileSource() {
-    if (mFd >= 0) {
-        ::close(mFd);
-        mFd = -1;
-    }
-}
-
-status_t ClearFileSource::initCheck() const {
-    return mFd >= 0 ? OK : NO_INIT;
-}
-
-ssize_t ClearFileSource::readAt(off64_t offset, void *data, size_t size) {
-    if (mFd < 0) {
-        return NO_INIT;
-    }
-
-    Mutex::Autolock autoLock(mLock);
-    if (mLength >= 0) {
-        if (offset >= mLength) {
-            return 0;  // read beyond EOF.
-        }
-        uint64_t numAvailable = mLength - offset;
-        if ((uint64_t)size > numAvailable) {
-            size = numAvailable;
-        }
-    }
-    return readAt_l(offset, data, size);
-}
-
-ssize_t ClearFileSource::readAt_l(off64_t offset, void *data, size_t size) {
-    off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET);
-    if (result == -1) {
-        ALOGE("seek to %lld failed", (long long)(offset + mOffset));
-        return UNKNOWN_ERROR;
-    }
-
-    return ::read(mFd, data, size);
-}
-
-status_t ClearFileSource::getSize(off64_t *size) {
-    Mutex::Autolock autoLock(mLock);
-
-    if (mFd < 0) {
-        return NO_INIT;
-    }
-
-    *size = mLength;
-
-    return OK;
-}
-
-}  // namespace android
diff --git a/media/libdatasource/ClearMediaHTTP.cpp b/media/libdatasource/ClearMediaHTTP.cpp
deleted file mode 100644
index 7249c84..0000000
--- a/media/libdatasource/ClearMediaHTTP.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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.
- */
-
-//#define LOG_NDEBUG 0
-#define LOG_TAG "ClearMediaHTTP"
-#include <utils/Log.h>
-
-#include <datasource/ClearMediaHTTP.h>
-
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/ALooper.h>
-#include <media/stagefright/FoundationUtils.h>
-
-#include <media/MediaHTTPConnection.h>
-
-namespace android {
-
-ClearMediaHTTP::ClearMediaHTTP(const sp<MediaHTTPConnection> &conn)
-    : mInitCheck((conn != NULL) ? OK : NO_INIT),
-      mHTTPConnection(conn),
-      mCachedSizeValid(false),
-      mCachedSize(0ll) {
-}
-
-ClearMediaHTTP::~ClearMediaHTTP() {
-}
-
-status_t ClearMediaHTTP::connect(
-        const char *uri,
-        const KeyedVector<String8, String8> *headers,
-        off64_t /* offset */) {
-    if (mInitCheck != OK) {
-        return mInitCheck;
-    }
-
-    KeyedVector<String8, String8> extHeaders;
-    if (headers != NULL) {
-        extHeaders = *headers;
-    }
-
-    if (extHeaders.indexOfKey(String8("User-Agent")) < 0) {
-        extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str()));
-    }
-
-    mLastURI = uri;
-    // reconnect() calls with uri == old mLastURI.c_str(), which gets zapped
-    // as part of the above assignment. Ensure no accidental later use.
-    uri = NULL;
-
-    bool success = mHTTPConnection->connect(mLastURI.c_str(), &extHeaders);
-
-    mLastHeaders = extHeaders;
-
-    mCachedSizeValid = false;
-
-    if (success) {
-        AString sanitized = uriDebugString(mLastURI);
-        mName = String8::format("ClearMediaHTTP(%s)", sanitized.c_str());
-    }
-
-    return success ? OK : UNKNOWN_ERROR;
-}
-
-void ClearMediaHTTP::close() {
-    disconnect();
-}
-
-void ClearMediaHTTP::disconnect() {
-    mName = String8("ClearMediaHTTP(<disconnected>)");
-    if (mInitCheck != OK) {
-        return;
-    }
-
-    mHTTPConnection->disconnect();
-}
-
-status_t ClearMediaHTTP::initCheck() const {
-    return mInitCheck;
-}
-
-ssize_t ClearMediaHTTP::readAt(off64_t offset, void *data, size_t size) {
-    if (mInitCheck != OK) {
-        return mInitCheck;
-    }
-
-    int64_t startTimeUs = ALooper::GetNowUs();
-
-    size_t numBytesRead = 0;
-    while (numBytesRead < size) {
-        size_t copy = size - numBytesRead;
-
-        if (copy > 64 * 1024) {
-            // limit the buffer sizes transferred across binder boundaries
-            // to avoid spurious transaction failures.
-            copy = 64 * 1024;
-        }
-
-        ssize_t n = mHTTPConnection->readAt(
-                offset + numBytesRead, (uint8_t *)data + numBytesRead, copy);
-
-        if (n < 0) {
-            return n;
-        } else if (n == 0) {
-            break;
-        }
-
-        numBytesRead += n;
-    }
-
-    int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
-
-    addBandwidthMeasurement(numBytesRead, delayUs);
-
-    return numBytesRead;
-}
-
-status_t ClearMediaHTTP::getSize(off64_t *size) {
-    if (mInitCheck != OK) {
-        return mInitCheck;
-    }
-
-    // Caching the returned size so that it stays valid even after a
-    // disconnect. NuCachedSource2 relies on this.
-
-    if (!mCachedSizeValid) {
-        mCachedSize = mHTTPConnection->getSize();
-        mCachedSizeValid = true;
-    }
-
-    *size = mCachedSize;
-
-    return *size < 0 ? *size : static_cast<status_t>(OK);
-}
-
-uint32_t ClearMediaHTTP::flags() {
-    return kWantsPrefetching | kIsHTTPBasedSource;
-}
-
-status_t ClearMediaHTTP::reconnectAtOffset(off64_t offset) {
-    return connect(mLastURI.c_str(), &mLastHeaders, offset);
-}
-
-
-String8 ClearMediaHTTP::getUri() {
-    if (mInitCheck != OK) {
-        return String8::empty();
-    }
-
-    String8 uri;
-    if (OK == mHTTPConnection->getUri(&uri)) {
-        return uri;
-    }
-    return String8(mLastURI.c_str());
-}
-
-String8 ClearMediaHTTP::getMIMEType() const {
-    if (mInitCheck != OK) {
-        return String8("application/octet-stream");
-    }
-
-    String8 mimeType;
-    status_t err = mHTTPConnection->getMIMEType(&mimeType);
-
-    if (err != OK) {
-        return String8("application/octet-stream");
-    }
-
-    return mimeType;
-}
-
-}  // namespace android
diff --git a/media/libdatasource/DataSourceFactory.cpp b/media/libdatasource/DataSourceFactory.cpp
index 8c772dd..bb6a08c 100644
--- a/media/libdatasource/DataSourceFactory.cpp
+++ b/media/libdatasource/DataSourceFactory.cpp
@@ -30,6 +30,19 @@
 namespace android {
 
 // static
+sp<DataSourceFactory> DataSourceFactory::sInstance;
+// static
+Mutex DataSourceFactory::sInstanceLock;
+
+// static
+sp<DataSourceFactory> DataSourceFactory::getInstance() {
+    Mutex::Autolock l(sInstanceLock);
+    if (!sInstance) {
+        sInstance = new DataSourceFactory();
+    }
+    return sInstance;
+}
+
 sp<DataSource> DataSourceFactory::CreateFromURI(
         const sp<MediaHTTPService> &httpService,
         const char *uri,
@@ -42,20 +55,16 @@
 
     sp<DataSource> source;
     if (!strncasecmp("file://", uri, 7)) {
-        source = new FileSource(uri + 7);
+        source = CreateFileSource(uri + 7);
     } else if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
         if (httpService == NULL) {
             ALOGE("Invalid http service!");
             return NULL;
         }
 
-        if (httpSource == NULL) {
-            sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
-            if (conn == NULL) {
-                ALOGE("Failed to make http connection from http service!");
-                return NULL;
-            }
-            httpSource = new MediaHTTP(conn);
+        sp<HTTPBase> mediaHTTP = httpSource;
+        if (mediaHTTP == NULL) {
+            mediaHTTP = static_cast<HTTPBase *>(CreateMediaHTTP(httpService).get());
         }
 
         String8 cacheConfig;
@@ -69,24 +78,24 @@
                     &disconnectAtHighwatermark);
         }
 
-        if (httpSource->connect(uri, &nonCacheSpecificHeaders) != OK) {
+        if (mediaHTTP->connect(uri, &nonCacheSpecificHeaders) != OK) {
             ALOGE("Failed to connect http source!");
             return NULL;
         }
 
         if (contentType != NULL) {
-            *contentType = httpSource->getMIMEType();
+            *contentType = mediaHTTP->getMIMEType();
         }
 
         source = NuCachedSource2::Create(
-                httpSource,
+                mediaHTTP,
                 cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
                 disconnectAtHighwatermark);
     } else if (!strncasecmp("data:", uri, 5)) {
         source = DataURISource::Create(uri);
     } else {
         // Assume it's a filename.
-        source = new FileSource(uri);
+        source = CreateFileSource(uri);
     }
 
     if (source == NULL || source->initCheck() != OK) {
@@ -108,10 +117,15 @@
 
     sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
     if (conn == NULL) {
+        ALOGE("Failed to make http connection from http service!");
         return NULL;
     } else {
         return new MediaHTTP(conn);
     }
 }
 
+sp<DataSource> DataSourceFactory::CreateFileSource(const char *uri) {
+    return new FileSource(uri);
+}
+
 }  // namespace android
diff --git a/media/libdatasource/FileSource.cpp b/media/libdatasource/FileSource.cpp
index 65780e3..bbf7dda 100644
--- a/media/libdatasource/FileSource.cpp
+++ b/media/libdatasource/FileSource.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -20,45 +20,84 @@
 
 #include <datasource/FileSource.h>
 #include <media/stagefright/foundation/ADebug.h>
-#include <private/android_filesystem_config.h>
+#include <media/stagefright/FoundationUtils.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 
 namespace android {
 
 FileSource::FileSource(const char *filename)
-    : ClearFileSource(filename),
-      mDecryptHandle(NULL),
-      mDrmManagerClient(NULL),
-      mDrmBufOffset(0),
-      mDrmBufSize(0),
-      mDrmBuf(NULL){
+    : mFd(-1),
+      mOffset(0),
+      mLength(-1),
+      mName("<null>") {
+
+    if (filename) {
+        mName = String8::format("FileSource(%s)", filename);
+    }
+    ALOGV("%s", filename);
+    mFd = open(filename, O_LARGEFILE | O_RDONLY);
+
+    if (mFd >= 0) {
+        mLength = lseek64(mFd, 0, SEEK_END);
+    } else {
+        ALOGE("Failed to open file '%s'. (%s)", filename, strerror(errno));
+    }
 }
 
 FileSource::FileSource(int fd, int64_t offset, int64_t length)
-    : ClearFileSource(fd, offset, length),
-      mDecryptHandle(NULL),
-      mDrmManagerClient(NULL),
-      mDrmBufOffset(0),
-      mDrmBufSize(0),
-      mDrmBuf(NULL) {
+    : mFd(fd),
+      mOffset(offset),
+      mLength(length),
+      mName("<null>") {
+    ALOGV("fd=%d (%s), offset=%lld, length=%lld",
+            fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
+
+    if (mOffset < 0) {
+        mOffset = 0;
+    }
+    if (mLength < 0) {
+        mLength = 0;
+    }
+    if (mLength > INT64_MAX - mOffset) {
+        mLength = INT64_MAX - mOffset;
+    }
+    struct stat s;
+    if (fstat(fd, &s) == 0) {
+        if (mOffset > s.st_size) {
+            mOffset = s.st_size;
+            mLength = 0;
+        }
+        if (mOffset + mLength > s.st_size) {
+            mLength = s.st_size - mOffset;
+        }
+    }
+    if (mOffset != offset || mLength != length) {
+        ALOGW("offset/length adjusted from %lld/%lld to %lld/%lld",
+                (long long) offset, (long long) length,
+                (long long) mOffset, (long long) mLength);
+    }
+
+    mName = String8::format(
+            "FileSource(fd(%s), %lld, %lld)",
+            nameForFd(fd).c_str(),
+            (long long) mOffset,
+            (long long) mLength);
+
 }
 
 FileSource::~FileSource() {
-    if (mDrmBuf != NULL) {
-        delete[] mDrmBuf;
-        mDrmBuf = NULL;
+    if (mFd >= 0) {
+        ::close(mFd);
+        mFd = -1;
     }
+}
 
-    if (mDecryptHandle != NULL) {
-        // To release mDecryptHandle
-        CHECK(mDrmManagerClient);
-        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
-        mDecryptHandle = NULL;
-    }
-
-    if (mDrmManagerClient != NULL) {
-        delete mDrmManagerClient;
-        mDrmManagerClient = NULL;
-    }
+status_t FileSource::initCheck() const {
+    return mFd >= 0 ? OK : NO_INIT;
 }
 
 ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) {
@@ -67,7 +106,6 @@
     }
 
     Mutex::Autolock autoLock(mLock);
-
     if (mLength >= 0) {
         if (offset >= mLength) {
             return 0;  // read beyond EOF.
@@ -77,79 +115,29 @@
             size = numAvailable;
         }
     }
-
-    if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
-            == mDecryptHandle->decryptApiType) {
-        return readAtDRM_l(offset, data, size);
-   } else {
-        return readAt_l(offset, data, size);
-    }
+    return readAt_l(offset, data, size);
 }
 
-sp<DecryptHandle> FileSource::DrmInitialization(const char *mime) {
-    if (getuid() == AID_MEDIA_EX) return nullptr; // no DRM in media extractor
-    if (mDrmManagerClient == NULL) {
-        mDrmManagerClient = new DrmManagerClient();
+ssize_t FileSource::readAt_l(off64_t offset, void *data, size_t size) {
+    off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET);
+    if (result == -1) {
+        ALOGE("seek to %lld failed", (long long)(offset + mOffset));
+        return UNKNOWN_ERROR;
     }
 
-    if (mDrmManagerClient == NULL) {
-        return NULL;
-    }
-
-    if (mDecryptHandle == NULL) {
-        mDecryptHandle = mDrmManagerClient->openDecryptSession(
-                mFd, mOffset, mLength, mime);
-    }
-
-    if (mDecryptHandle == NULL) {
-        delete mDrmManagerClient;
-        mDrmManagerClient = NULL;
-    }
-
-    return mDecryptHandle;
+    return ::read(mFd, data, size);
 }
 
-ssize_t FileSource::readAtDRM_l(off64_t offset, void *data, size_t size) {
-    size_t DRM_CACHE_SIZE = 1024;
-    if (mDrmBuf == NULL) {
-        mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
+status_t FileSource::getSize(off64_t *size) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mFd < 0) {
+        return NO_INIT;
     }
 
-    if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
-            && (offset + mOffset + size) <= static_cast<size_t>(mDrmBufOffset + mDrmBufSize)) {
-        /* Use buffered data */
-        memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
-        return size;
-    } else if (size <= DRM_CACHE_SIZE) {
-        /* Buffer new data */
-        mDrmBufOffset =  offset + mOffset;
-        mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
-                DRM_CACHE_SIZE, offset + mOffset);
-        if (mDrmBufSize > 0) {
-            int64_t dataRead = 0;
-            dataRead = size > static_cast<size_t>(mDrmBufSize) ? mDrmBufSize : size;
-            memcpy(data, (void*)mDrmBuf, dataRead);
-            return dataRead;
-        } else {
-            return mDrmBufSize;
-        }
-    } else {
-        /* Too big chunk to cache. Call DRM directly */
-        return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
-    }
-}
+    *size = mLength;
 
-/* static */
-bool FileSource::requiresDrm(int fd, int64_t offset, int64_t length, const char *mime) {
-    std::unique_ptr<DrmManagerClient> drmClient(new DrmManagerClient());
-    sp<DecryptHandle> decryptHandle =
-            drmClient->openDecryptSession(fd, offset, length, mime);
-    bool requiresDrm = false;
-    if (decryptHandle != nullptr) {
-        requiresDrm = decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED;
-        drmClient->closeDecryptSession(decryptHandle);
-    }
-    return requiresDrm;
+    return OK;
 }
 
 }  // namespace android
diff --git a/media/libdatasource/MediaHTTP.cpp b/media/libdatasource/MediaHTTP.cpp
index e57510d..58c1ce8 100644
--- a/media/libdatasource/MediaHTTP.cpp
+++ b/media/libdatasource/MediaHTTP.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -20,7 +20,6 @@
 
 #include <datasource/MediaHTTP.h>
 
-#include <binder/IServiceManager.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
 #include <media/stagefright/FoundationUtils.h>
@@ -30,45 +29,156 @@
 namespace android {
 
 MediaHTTP::MediaHTTP(const sp<MediaHTTPConnection> &conn)
-    : ClearMediaHTTP(conn),
-      mDrmManagerClient(NULL) {
+    : mInitCheck((conn != NULL) ? OK : NO_INIT),
+      mHTTPConnection(conn),
+      mCachedSizeValid(false),
+      mCachedSize(0ll) {
 }
 
 MediaHTTP::~MediaHTTP() {
-    clearDRMState_l();
 }
 
-// DRM...
-
-sp<DecryptHandle> MediaHTTP::DrmInitialization(const char* mime) {
-    if (mDrmManagerClient == NULL) {
-        mDrmManagerClient = new DrmManagerClient();
+status_t MediaHTTP::connect(
+        const char *uri,
+        const KeyedVector<String8, String8> *headers,
+        off64_t /* offset */) {
+    if (mInitCheck != OK) {
+        return mInitCheck;
     }
 
-    if (mDrmManagerClient == NULL) {
-        return NULL;
+    KeyedVector<String8, String8> extHeaders;
+    if (headers != NULL) {
+        extHeaders = *headers;
     }
 
-    if (mDecryptHandle == NULL) {
-        mDecryptHandle = mDrmManagerClient->openDecryptSession(
-                String8(mLastURI.c_str()), mime);
+    if (extHeaders.indexOfKey(String8("User-Agent")) < 0) {
+        extHeaders.add(String8("User-Agent"), String8(MakeUserAgent().c_str()));
     }
 
-    if (mDecryptHandle == NULL) {
-        delete mDrmManagerClient;
-        mDrmManagerClient = NULL;
+    mLastURI = uri;
+    // reconnect() calls with uri == old mLastURI.c_str(), which gets zapped
+    // as part of the above assignment. Ensure no accidental later use.
+    uri = NULL;
+
+    bool success = mHTTPConnection->connect(mLastURI.c_str(), &extHeaders);
+
+    mLastHeaders = extHeaders;
+
+    mCachedSizeValid = false;
+
+    if (success) {
+        AString sanitized = uriDebugString(mLastURI);
+        mName = String8::format("MediaHTTP(%s)", sanitized.c_str());
     }
 
-    return mDecryptHandle;
+    return success ? OK : UNKNOWN_ERROR;
 }
 
-void MediaHTTP::clearDRMState_l() {
-    if (mDecryptHandle != NULL) {
-        // To release mDecryptHandle
-        CHECK(mDrmManagerClient);
-        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
-        mDecryptHandle = NULL;
+void MediaHTTP::close() {
+    disconnect();
+}
+
+void MediaHTTP::disconnect() {
+    mName = String8("MediaHTTP(<disconnected>)");
+    if (mInitCheck != OK) {
+        return;
     }
+
+    mHTTPConnection->disconnect();
+}
+
+status_t MediaHTTP::initCheck() const {
+    return mInitCheck;
+}
+
+ssize_t MediaHTTP::readAt(off64_t offset, void *data, size_t size) {
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    int64_t startTimeUs = ALooper::GetNowUs();
+
+    size_t numBytesRead = 0;
+    while (numBytesRead < size) {
+        size_t copy = size - numBytesRead;
+
+        if (copy > 64 * 1024) {
+            // limit the buffer sizes transferred across binder boundaries
+            // to avoid spurious transaction failures.
+            copy = 64 * 1024;
+        }
+
+        ssize_t n = mHTTPConnection->readAt(
+                offset + numBytesRead, (uint8_t *)data + numBytesRead, copy);
+
+        if (n < 0) {
+            return n;
+        } else if (n == 0) {
+            break;
+        }
+
+        numBytesRead += n;
+    }
+
+    int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
+
+    addBandwidthMeasurement(numBytesRead, delayUs);
+
+    return numBytesRead;
+}
+
+status_t MediaHTTP::getSize(off64_t *size) {
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    // Caching the returned size so that it stays valid even after a
+    // disconnect. NuCachedSource2 relies on this.
+
+    if (!mCachedSizeValid) {
+        mCachedSize = mHTTPConnection->getSize();
+        mCachedSizeValid = true;
+    }
+
+    *size = mCachedSize;
+
+    return *size < 0 ? *size : static_cast<status_t>(OK);
+}
+
+uint32_t MediaHTTP::flags() {
+    return kWantsPrefetching | kIsHTTPBasedSource;
+}
+
+status_t MediaHTTP::reconnectAtOffset(off64_t offset) {
+    return connect(mLastURI.c_str(), &mLastHeaders, offset);
+}
+
+
+String8 MediaHTTP::getUri() {
+    if (mInitCheck != OK) {
+        return String8::empty();
+    }
+
+    String8 uri;
+    if (OK == mHTTPConnection->getUri(&uri)) {
+        return uri;
+    }
+    return String8(mLastURI.c_str());
+}
+
+String8 MediaHTTP::getMIMEType() const {
+    if (mInitCheck != OK) {
+        return String8("application/octet-stream");
+    }
+
+    String8 mimeType;
+    status_t err = mHTTPConnection->getMIMEType(&mimeType);
+
+    if (err != OK) {
+        return String8("application/octet-stream");
+    }
+
+    return mimeType;
 }
 
 }  // namespace android
diff --git a/media/libdatasource/include/datasource/ClearFileSource.h b/media/libdatasource/include/datasource/ClearFileSource.h
deleted file mode 100644
index be83748..0000000
--- a/media/libdatasource/include/datasource/ClearFileSource.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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 CLEAR_FILE_SOURCE_H_
-
-#define CLEAR_FILE_SOURCE_H_
-
-#include <stdio.h>
-
-#include <media/DataSource.h>
-#include <media/stagefright/MediaErrors.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class ClearFileSource : public DataSource {
-public:
-    ClearFileSource(const char *filename);
-    // ClearFileSource takes ownership and will close the fd
-    ClearFileSource(int fd, int64_t offset, int64_t length);
-
-    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() {
-        return kIsLocalFileSource;
-    }
-
-    virtual String8 toString() {
-        return mName;
-    }
-
-protected:
-    virtual ~ClearFileSource();
-    virtual ssize_t readAt_l(off64_t offset, void *data, size_t size);
-
-    int mFd;
-    int64_t mOffset;
-    int64_t mLength;
-    Mutex mLock;
-
-private:
-    String8 mName;
-
-    ClearFileSource(const ClearFileSource &);
-    ClearFileSource &operator=(const ClearFileSource &);
-};
-
-}  // namespace android
-
-#endif  // CLEAR_FILE_SOURCE_H_
-
diff --git a/media/libdatasource/include/datasource/ClearMediaHTTP.h b/media/libdatasource/include/datasource/ClearMediaHTTP.h
deleted file mode 100644
index 5440a3a..0000000
--- a/media/libdatasource/include/datasource/ClearMediaHTTP.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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 CLEAR_MEDIA_HTTP_H_
-
-#define CLEAR_MEDIA_HTTP_H_
-
-#include <media/stagefright/foundation/AString.h>
-
-#include "HTTPBase.h"
-
-namespace android {
-
-struct MediaHTTPConnection;
-
-struct ClearMediaHTTP : public HTTPBase {
-    ClearMediaHTTP(const sp<MediaHTTPConnection> &conn);
-
-    virtual status_t connect(
-            const char *uri,
-            const KeyedVector<String8, String8> *headers,
-            off64_t offset);
-
-    virtual void close();
-
-    virtual void disconnect();
-
-    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();
-
-    virtual status_t reconnectAtOffset(off64_t offset);
-
-protected:
-    virtual ~ClearMediaHTTP();
-
-    virtual String8 getUri();
-    virtual String8 getMIMEType() const;
-
-    AString mLastURI;
-
-private:
-    status_t mInitCheck;
-    sp<MediaHTTPConnection> mHTTPConnection;
-
-    KeyedVector<String8, String8> mLastHeaders;
-
-    bool mCachedSizeValid;
-    off64_t mCachedSize;
-
-    DISALLOW_EVIL_CONSTRUCTORS(ClearMediaHTTP);
-};
-
-}  // namespace android
-
-#endif  // CLEAR_MEDIA_HTTP_H_
diff --git a/media/libdatasource/include/datasource/DataSourceFactory.h b/media/libdatasource/include/datasource/DataSourceFactory.h
index 6e313d3..194abe2 100644
--- a/media/libdatasource/include/datasource/DataSourceFactory.h
+++ b/media/libdatasource/include/datasource/DataSourceFactory.h
@@ -29,17 +29,27 @@
 class String8;
 struct HTTPBase;
 
-class DataSourceFactory {
+class DataSourceFactory : public RefBase {
 public:
-    static sp<DataSource> CreateFromURI(
+    static sp<DataSourceFactory> getInstance();
+    sp<DataSource> CreateFromURI(
             const sp<MediaHTTPService> &httpService,
             const char *uri,
             const KeyedVector<String8, String8> *headers = NULL,
             String8 *contentType = NULL,
             HTTPBase *httpSource = NULL);
 
-    static sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
-    static sp<DataSource> CreateFromFd(int fd, int64_t offset, int64_t length);
+    virtual sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
+    sp<DataSource> CreateFromFd(int fd, int64_t offset, int64_t length);
+
+protected:
+    virtual sp<DataSource> CreateFileSource(const char *uri);
+    DataSourceFactory() {};
+    virtual ~DataSourceFactory() {};
+
+private:
+    static sp<DataSourceFactory> sInstance;
+    static Mutex sInstanceLock;
 };
 
 }  // namespace android
diff --git a/media/libdatasource/include/datasource/FileSource.h b/media/libdatasource/include/datasource/FileSource.h
index 9249842..dee0c33 100644
--- a/media/libdatasource/include/datasource/FileSource.h
+++ b/media/libdatasource/include/datasource/FileSource.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * 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.
@@ -20,37 +20,43 @@
 
 #include <stdio.h>
 
-#include <datasource/ClearFileSource.h>
+#include <media/DataSource.h>
 #include <media/stagefright/MediaErrors.h>
 #include <utils/threads.h>
-#include <drm/DrmManagerClient.h>
 
 namespace android {
 
-class FileSource : public ClearFileSource {
+class FileSource : public DataSource {
 public:
     FileSource(const char *filename);
     // FileSource takes ownership and will close the fd
     FileSource(int fd, int64_t offset, int64_t length);
 
+    virtual status_t initCheck() const;
+
     virtual ssize_t readAt(off64_t offset, void *data, size_t size);
 
-    virtual sp<DecryptHandle> DrmInitialization(const char *mime);
+    virtual status_t getSize(off64_t *size);
 
-    static bool requiresDrm(int fd, int64_t offset, int64_t length, const char *mime);
+    virtual uint32_t flags() {
+        return kIsLocalFileSource;
+    }
+
+    virtual String8 toString() {
+        return mName;
+    }
 
 protected:
     virtual ~FileSource();
+    virtual ssize_t readAt_l(off64_t offset, void *data, size_t size);
+
+    int mFd;
+    int64_t mOffset;
+    int64_t mLength;
+    Mutex mLock;
 
 private:
-    /*for DRM*/
-    sp<DecryptHandle> mDecryptHandle;
-    DrmManagerClient *mDrmManagerClient;
-    int64_t mDrmBufOffset;
-    ssize_t mDrmBufSize;
-    unsigned char *mDrmBuf;
-
-    ssize_t readAtDRM_l(off64_t offset, void *data, size_t size);
+    String8 mName;
 
     FileSource(const FileSource &);
     FileSource &operator=(const FileSource &);
diff --git a/media/libdatasource/include/datasource/MediaHTTP.h b/media/libdatasource/include/datasource/MediaHTTP.h
index 60252ce..a8d203b 100644
--- a/media/libdatasource/include/datasource/MediaHTTP.h
+++ b/media/libdatasource/include/datasource/MediaHTTP.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -18,26 +18,52 @@
 
 #define MEDIA_HTTP_H_
 
-#include <datasource/ClearMediaHTTP.h>
 #include <media/stagefright/foundation/AString.h>
 
+#include "HTTPBase.h"
+
 namespace android {
 
 struct MediaHTTPConnection;
 
-struct MediaHTTP : public ClearMediaHTTP {
+struct MediaHTTP : public HTTPBase {
     MediaHTTP(const sp<MediaHTTPConnection> &conn);
 
+    virtual status_t connect(
+            const char *uri,
+            const KeyedVector<String8, String8> *headers,
+            off64_t offset);
+
+    virtual void close();
+
+    virtual void disconnect();
+
+    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();
+
+    virtual status_t reconnectAtOffset(off64_t offset);
+
 protected:
     virtual ~MediaHTTP();
 
-    virtual sp<DecryptHandle> DrmInitialization(const char* mime);
+    virtual String8 getUri();
+    virtual String8 getMIMEType() const;
+
+    AString mLastURI;
 
 private:
-    sp<DecryptHandle> mDecryptHandle;
-    DrmManagerClient *mDrmManagerClient;
+    status_t mInitCheck;
+    sp<MediaHTTPConnection> mHTTPConnection;
 
-    void clearDRMState_l();
+    KeyedVector<String8, String8> mLastHeaders;
+
+    bool mCachedSizeValid;
+    off64_t mCachedSize;
 
     DISALLOW_EVIL_CONSTRUCTORS(MediaHTTP);
 };
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index fdab14a..ec4751c 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -285,7 +285,6 @@
         "mediarecorder.cpp",
         "IMediaMetadataRetriever.cpp",
         "mediametadataretriever.cpp",
-        "MidiDeviceInfo.cpp",
         "MediaScanner.cpp",
         "MediaScannerClient.cpp",
         "CharacterEncodingDetector.cpp",
diff --git a/media/libmedia/MidiDeviceInfo.cpp b/media/libmedia/MidiDeviceInfo.cpp
deleted file mode 100644
index 7588e00..0000000
--- a/media/libmedia/MidiDeviceInfo.cpp
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2016 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.
- */
-
-#define LOG_TAG "MidiDeviceInfo"
-
-#include <media/MidiDeviceInfo.h>
-
-#include <binder/Parcel.h>
-#include <log/log.h>
-#include <utils/Errors.h>
-#include <utils/String16.h>
-
-namespace android {
-namespace media {
-namespace midi {
-
-// The constant values need to be kept in sync with MidiDeviceInfo.java.
-// static
-const char* const MidiDeviceInfo::PROPERTY_NAME = "name";
-const char* const MidiDeviceInfo::PROPERTY_MANUFACTURER = "manufacturer";
-const char* const MidiDeviceInfo::PROPERTY_PRODUCT = "product";
-const char* const MidiDeviceInfo::PROPERTY_VERSION = "version";
-const char* const MidiDeviceInfo::PROPERTY_SERIAL_NUMBER = "serial_number";
-const char* const MidiDeviceInfo::PROPERTY_ALSA_CARD = "alsa_card";
-const char* const MidiDeviceInfo::PROPERTY_ALSA_DEVICE = "alsa_device";
-
-String16 MidiDeviceInfo::getProperty(const char* propertyName) {
-    String16 value;
-    if (mProperties.getString(String16(propertyName), &value)) {
-        return value;
-    } else {
-        return String16();
-    }
-}
-
-#define RETURN_IF_FAILED(calledOnce)                                     \
-    {                                                                    \
-        status_t returnStatus = calledOnce;                              \
-        if (returnStatus) {                                              \
-            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
-            return returnStatus;                                         \
-         }                                                               \
-    }
-
-status_t MidiDeviceInfo::writeToParcel(Parcel* parcel) const {
-    // Needs to be kept in sync with code in MidiDeviceInfo.java
-    RETURN_IF_FAILED(parcel->writeInt32(mType));
-    RETURN_IF_FAILED(parcel->writeInt32(mId));
-    RETURN_IF_FAILED(parcel->writeInt32((int32_t)mInputPortNames.size()));
-    RETURN_IF_FAILED(parcel->writeInt32((int32_t)mOutputPortNames.size()));
-    RETURN_IF_FAILED(writeStringVector(parcel, mInputPortNames));
-    RETURN_IF_FAILED(writeStringVector(parcel, mOutputPortNames));
-    RETURN_IF_FAILED(parcel->writeInt32(mIsPrivate ? 1 : 0));
-    RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
-    // This corresponds to "extra" properties written by Java code
-    RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
-    return OK;
-}
-
-status_t MidiDeviceInfo::readFromParcel(const Parcel* parcel) {
-    // Needs to be kept in sync with code in MidiDeviceInfo.java
-    RETURN_IF_FAILED(parcel->readInt32(&mType));
-    RETURN_IF_FAILED(parcel->readInt32(&mId));
-    int32_t inputPortCount;
-    RETURN_IF_FAILED(parcel->readInt32(&inputPortCount));
-    int32_t outputPortCount;
-    RETURN_IF_FAILED(parcel->readInt32(&outputPortCount));
-    RETURN_IF_FAILED(readStringVector(parcel, &mInputPortNames, inputPortCount));
-    RETURN_IF_FAILED(readStringVector(parcel, &mOutputPortNames, outputPortCount));
-    int32_t isPrivate;
-    RETURN_IF_FAILED(parcel->readInt32(&isPrivate));
-    mIsPrivate = isPrivate == 1;
-    RETURN_IF_FAILED(mProperties.readFromParcel(parcel));
-    // Ignore "extra" properties as they may contain Java Parcelables
-    return OK;
-}
-
-status_t MidiDeviceInfo::readStringVector(
-        const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength) {
-    std::unique_ptr<std::vector<std::unique_ptr<String16>>> v;
-    status_t result = parcel->readString16Vector(&v);
-    if (result != OK) return result;
-    vectorPtr->clear();
-    if (v.get() != nullptr) {
-        for (const auto& iter : *v) {
-            if (iter.get() != nullptr) {
-                vectorPtr->push_back(*iter);
-            } else {
-                vectorPtr->push_back(String16());
-            }
-        }
-    } else {
-        vectorPtr->resize(defaultLength);
-    }
-    return OK;
-}
-
-status_t MidiDeviceInfo::writeStringVector(Parcel* parcel, const Vector<String16>& vector) const {
-    std::vector<String16> v;
-    for (size_t i = 0; i < vector.size(); ++i) {
-        v.push_back(vector[i]);
-    }
-    return parcel->writeString16Vector(v);
-}
-
-// Vector does not define operator==
-static inline bool areVectorsEqual(const Vector<String16>& lhs, const Vector<String16>& rhs) {
-    if (lhs.size() != rhs.size()) return false;
-    for (size_t i = 0; i < lhs.size(); ++i) {
-        if (lhs[i] != rhs[i]) return false;
-    }
-    return true;
-}
-
-bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
-    return (lhs.mType == rhs.mType && lhs.mId == rhs.mId &&
-            areVectorsEqual(lhs.mInputPortNames, rhs.mInputPortNames) &&
-            areVectorsEqual(lhs.mOutputPortNames, rhs.mOutputPortNames) &&
-            lhs.mProperties == rhs.mProperties &&
-            lhs.mIsPrivate == rhs.mIsPrivate);
-}
-
-}  // namespace midi
-}  // namespace media
-}  // namespace android
diff --git a/media/libmedia/include/media/MidiDeviceInfo.h b/media/libmedia/include/media/MidiDeviceInfo.h
deleted file mode 100644
index 5b4a241..0000000
--- a/media/libmedia/include/media/MidiDeviceInfo.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2016 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 ANDROID_MEDIA_MIDI_DEVICE_INFO_H
-#define ANDROID_MEDIA_MIDI_DEVICE_INFO_H
-
-#include <binder/Parcelable.h>
-#include <binder/PersistableBundle.h>
-#include <utils/String16.h>
-#include <utils/Vector.h>
-
-namespace android {
-namespace media {
-namespace midi {
-
-class MidiDeviceInfo : public Parcelable {
-public:
-    MidiDeviceInfo() = default;
-    virtual ~MidiDeviceInfo() = default;
-    MidiDeviceInfo(const MidiDeviceInfo& midiDeviceInfo) = default;
-
-    status_t writeToParcel(Parcel* parcel) const override;
-    status_t readFromParcel(const Parcel* parcel) override;
-
-    int getType() const { return mType; }
-    int getUid() const { return mId; }
-    bool isPrivate() const { return mIsPrivate; }
-    const Vector<String16>& getInputPortNames() const { return mInputPortNames; }
-    const Vector<String16>&  getOutputPortNames() const { return mOutputPortNames; }
-    String16 getProperty(const char* propertyName);
-
-    // The constants need to be kept in sync with MidiDeviceInfo.java
-    enum {
-        TYPE_USB = 1,
-        TYPE_VIRTUAL = 2,
-        TYPE_BLUETOOTH = 3,
-    };
-    static const char* const PROPERTY_NAME;
-    static const char* const PROPERTY_MANUFACTURER;
-    static const char* const PROPERTY_PRODUCT;
-    static const char* const PROPERTY_VERSION;
-    static const char* const PROPERTY_SERIAL_NUMBER;
-    static const char* const PROPERTY_ALSA_CARD;
-    static const char* const PROPERTY_ALSA_DEVICE;
-
-    friend bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs);
-    friend bool operator!=(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
-        return !(lhs == rhs);
-    }
-
-private:
-    status_t readStringVector(
-            const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength);
-    status_t writeStringVector(Parcel* parcel, const Vector<String16>& vector) const;
-
-    int32_t mType;
-    int32_t mId;
-    Vector<String16> mInputPortNames;
-    Vector<String16> mOutputPortNames;
-    os::PersistableBundle mProperties;
-    bool mIsPrivate;
-};
-
-}  // namespace midi
-}  // namespace media
-}  // namespace android
-
-#endif  // ANDROID_MEDIA_MIDI_DEVICE_INFO_H
diff --git a/media/libmediaplayerservice/Android.bp b/media/libmediaplayerservice/Android.bp
index 6701017..5301f5c 100644
--- a/media/libmediaplayerservice/Android.bp
+++ b/media/libmediaplayerservice/Android.bp
@@ -7,6 +7,7 @@
         "MediaPlayerService.cpp",
         "MediaRecorderClient.cpp",
         "MetadataRetrieverClient.cpp",
+        "StagefrightMetadataRetriever.cpp",
         "StagefrightRecorder.cpp",
         "TestPlayerStub.cpp",
     ],
@@ -23,6 +24,7 @@
         "libcutils",
         "libdatasource",
         "libdl",
+        "libdrmframework",
         "libgui",
         "libhidlbase",
         "liblog",
@@ -46,6 +48,7 @@
     ],
 
     static_libs: [
+        "libplayerservice_datasource",
         "libstagefright_nuplayer",
         "libstagefright_rtsp",
         "libstagefright_timedtext",
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
similarity index 98%
rename from media/libstagefright/StagefrightMetadataRetriever.cpp
rename to media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
index c157ede..1aae241 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libmediaplayerservice/StagefrightMetadataRetriever.cpp
@@ -22,11 +22,11 @@
 #include <utils/Log.h>
 #include <cutils/properties.h>
 
-#include "include/FrameDecoder.h"
-#include "include/StagefrightMetadataRetriever.h"
+#include "StagefrightMetadataRetriever.h"
+#include "FrameDecoder.h"
 
-#include <datasource/DataSourceFactory.h>
-#include <datasource/FileSource.h>
+#include <datasource/PlayerServiceDataSourceFactory.h>
+#include <datasource/PlayerServiceFileSource.h>
 #include <media/IMediaHTTPService.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -63,7 +63,8 @@
     ALOGV("setDataSource(%s)", uri);
 
     clearMetadata();
-    mSource = DataSourceFactory::CreateFromURI(httpService, uri, headers);
+    mSource = PlayerServiceDataSourceFactory::getInstance()->CreateFromURI(
+            httpService, uri, headers);
 
     if (mSource == NULL) {
         ALOGE("Unable to create data source for '%s'.", uri);
@@ -91,7 +92,7 @@
     ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
 
     clearMetadata();
-    mSource = new FileSource(fd, offset, length);
+    mSource = new PlayerServiceFileSource(fd, offset, length);
 
     status_t err;
     if ((err = mSource->initCheck()) != OK) {
diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libmediaplayerservice/StagefrightMetadataRetriever.h
similarity index 100%
rename from media/libstagefright/include/StagefrightMetadataRetriever.h
rename to media/libmediaplayerservice/StagefrightMetadataRetriever.h
diff --git a/media/libmediaplayerservice/datasource/Android.bp b/media/libmediaplayerservice/datasource/Android.bp
new file mode 100644
index 0000000..71fa50b
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/Android.bp
@@ -0,0 +1,43 @@
+cc_library_static {
+    name: "libplayerservice_datasource",
+
+    srcs: [
+        "PlayerServiceDataSourceFactory.cpp",
+        "PlayerServiceFileSource.cpp",
+        "PlayerServiceMediaHTTP.cpp",
+    ],
+
+    header_libs: [
+        "media_ndk_headers",
+        "libmedia_headers",
+    ],
+
+    shared_libs: [
+        "libdatasource",
+        "libdrmframework",
+        "liblog",
+        "libutils",
+    ],
+
+    local_include_dirs: [
+        "include",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    cflags: [
+        "-Werror",
+        "-Wno-error=deprecated-declarations",
+        "-Wall",
+    ],
+
+    sanitize: {
+        misc_undefined: [
+            "unsigned-integer-overflow",
+            "signed-integer-overflow",
+        ],
+        cfi: true,
+    },
+}
diff --git a/media/libmediaplayerservice/datasource/PlayerServiceDataSourceFactory.cpp b/media/libmediaplayerservice/datasource/PlayerServiceDataSourceFactory.cpp
new file mode 100644
index 0000000..ef946e9
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/PlayerServiceDataSourceFactory.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+//#define LOG_NDEBUG 0
+#define LOG_TAG "PlayerServuceDataSourceFactory"
+
+
+#include <datasource/PlayerServiceDataSourceFactory.h>
+#include <datasource/PlayerServiceFileSource.h>
+#include <datasource/PlayerServiceMediaHTTP.h>
+#include <media/MediaHTTPConnection.h>
+#include <media/MediaHTTPService.h>
+
+namespace android {
+
+// static
+sp<PlayerServiceDataSourceFactory> PlayerServiceDataSourceFactory::sInstance;
+// static
+Mutex PlayerServiceDataSourceFactory::sInstanceLock;
+
+// static
+sp<PlayerServiceDataSourceFactory> PlayerServiceDataSourceFactory::getInstance() {
+    Mutex::Autolock l(sInstanceLock);
+    if (!sInstance) {
+        sInstance = new PlayerServiceDataSourceFactory();
+    }
+    return sInstance;
+}
+
+sp<DataSource> PlayerServiceDataSourceFactory::CreateMediaHTTP(
+        const sp<MediaHTTPService> &httpService) {
+    if (httpService == NULL) {
+        return NULL;
+    }
+
+    sp<MediaHTTPConnection> conn = httpService->makeHTTPConnection();
+    if (conn == NULL) {
+        ALOGE("Failed to make http connection from http service!");
+        return NULL;
+    } else {
+        return new PlayerServiceMediaHTTP(conn);
+    }
+}
+
+sp<DataSource> PlayerServiceDataSourceFactory::CreateFileSource(const char *uri) {
+    return new PlayerServiceFileSource(uri);
+}
+
+}  // namespace android
diff --git a/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
new file mode 100644
index 0000000..1580891
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/PlayerServiceFileSource.cpp
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "PlayerServiceFileSource"
+#include <utils/Log.h>
+
+#include <datasource/PlayerServiceFileSource.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <private/android_filesystem_config.h>
+
+namespace android {
+
+PlayerServiceFileSource::PlayerServiceFileSource(const char *filename)
+    : FileSource(filename),
+      mDecryptHandle(NULL),
+      mDrmManagerClient(NULL),
+      mDrmBufOffset(0),
+      mDrmBufSize(0),
+      mDrmBuf(NULL){
+}
+
+PlayerServiceFileSource::PlayerServiceFileSource(int fd, int64_t offset, int64_t length)
+    : FileSource(fd, offset, length),
+      mDecryptHandle(NULL),
+      mDrmManagerClient(NULL),
+      mDrmBufOffset(0),
+      mDrmBufSize(0),
+      mDrmBuf(NULL) {
+}
+
+PlayerServiceFileSource::~PlayerServiceFileSource() {
+    if (mDrmBuf != NULL) {
+        delete[] mDrmBuf;
+        mDrmBuf = NULL;
+    }
+
+    if (mDecryptHandle != NULL) {
+        // To release mDecryptHandle
+        CHECK(mDrmManagerClient);
+        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+        mDecryptHandle = NULL;
+    }
+
+    if (mDrmManagerClient != NULL) {
+        delete mDrmManagerClient;
+        mDrmManagerClient = NULL;
+    }
+}
+
+ssize_t PlayerServiceFileSource::readAt(off64_t offset, void *data, size_t size) {
+    if (mFd < 0) {
+        return NO_INIT;
+    }
+
+    Mutex::Autolock autoLock(mLock);
+
+    if (mLength >= 0) {
+        if (offset >= mLength) {
+            return 0;  // read beyond EOF.
+        }
+        uint64_t numAvailable = mLength - offset;
+        if ((uint64_t)size > numAvailable) {
+            size = numAvailable;
+        }
+    }
+
+    if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
+            == mDecryptHandle->decryptApiType) {
+        return readAtDRM_l(offset, data, size);
+   } else {
+        return readAt_l(offset, data, size);
+    }
+}
+
+sp<DecryptHandle> PlayerServiceFileSource::DrmInitialization(const char *mime) {
+    if (getuid() == AID_MEDIA_EX) return nullptr; // no DRM in media extractor
+    if (mDrmManagerClient == NULL) {
+        mDrmManagerClient = new DrmManagerClient();
+    }
+
+    if (mDrmManagerClient == NULL) {
+        return NULL;
+    }
+
+    if (mDecryptHandle == NULL) {
+        mDecryptHandle = mDrmManagerClient->openDecryptSession(
+                mFd, mOffset, mLength, mime);
+    }
+
+    if (mDecryptHandle == NULL) {
+        delete mDrmManagerClient;
+        mDrmManagerClient = NULL;
+    }
+
+    return mDecryptHandle;
+}
+
+ssize_t PlayerServiceFileSource::readAtDRM_l(off64_t offset, void *data, size_t size) {
+    size_t DRM_CACHE_SIZE = 1024;
+    if (mDrmBuf == NULL) {
+        mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
+    }
+
+    if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
+            && (offset + mOffset + size) <= static_cast<size_t>(mDrmBufOffset + mDrmBufSize)) {
+        /* Use buffered data */
+        memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
+        return size;
+    } else if (size <= DRM_CACHE_SIZE) {
+        /* Buffer new data */
+        mDrmBufOffset =  offset + mOffset;
+        mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
+                DRM_CACHE_SIZE, offset + mOffset);
+        if (mDrmBufSize > 0) {
+            int64_t dataRead = 0;
+            dataRead = size > static_cast<size_t>(mDrmBufSize) ? mDrmBufSize : size;
+            memcpy(data, (void*)mDrmBuf, dataRead);
+            return dataRead;
+        } else {
+            return mDrmBufSize;
+        }
+    } else {
+        /* Too big chunk to cache. Call DRM directly */
+        return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
+    }
+}
+
+/* static */
+bool PlayerServiceFileSource::requiresDrm(int fd, int64_t offset, int64_t length, const char *mime) {
+    std::unique_ptr<DrmManagerClient> drmClient(new DrmManagerClient());
+    sp<DecryptHandle> decryptHandle =
+            drmClient->openDecryptSession(fd, offset, length, mime);
+    bool requiresDrm = false;
+    if (decryptHandle != nullptr) {
+        requiresDrm = decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED;
+        drmClient->closeDecryptSession(decryptHandle);
+    }
+    return requiresDrm;
+}
+
+}  // namespace android
diff --git a/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp b/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
new file mode 100644
index 0000000..0124720
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/PlayerServiceMediaHTTP.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "PlayerServiceMediaHTTP"
+#include <utils/Log.h>
+
+#include <datasource/PlayerServiceMediaHTTP.h>
+
+#include <binder/IServiceManager.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/FoundationUtils.h>
+
+#include <media/MediaHTTPConnection.h>
+
+namespace android {
+
+PlayerServiceMediaHTTP::PlayerServiceMediaHTTP(const sp<MediaHTTPConnection> &conn)
+    : MediaHTTP(conn),
+      mDrmManagerClient(NULL) {
+}
+
+PlayerServiceMediaHTTP::~PlayerServiceMediaHTTP() {
+    clearDRMState_l();
+}
+
+// DRM...
+
+sp<DecryptHandle> PlayerServiceMediaHTTP::DrmInitialization(const char* mime) {
+    if (mDrmManagerClient == NULL) {
+        mDrmManagerClient = new DrmManagerClient();
+    }
+
+    if (mDrmManagerClient == NULL) {
+        return NULL;
+    }
+
+    if (mDecryptHandle == NULL) {
+        mDecryptHandle = mDrmManagerClient->openDecryptSession(
+                String8(mLastURI.c_str()), mime);
+    }
+
+    if (mDecryptHandle == NULL) {
+        delete mDrmManagerClient;
+        mDrmManagerClient = NULL;
+    }
+
+    return mDecryptHandle;
+}
+
+void PlayerServiceMediaHTTP::clearDRMState_l() {
+    if (mDecryptHandle != NULL) {
+        // To release mDecryptHandle
+        CHECK(mDrmManagerClient);
+        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+        mDecryptHandle = NULL;
+    }
+}
+
+}  // namespace android
diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceDataSourceFactory.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceDataSourceFactory.h
new file mode 100644
index 0000000..7d58c5c
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceDataSourceFactory.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 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 PLAYER_SERVICE_DATA_SOURCE_FACTORY_H_
+
+#define PLAYER_SERVICE_DATA_SOURCE_FACTORY_H_
+
+#include <datasource/DataSourceFactory.h>
+#include <media/DataSource.h>
+#include <sys/types.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+struct MediaHTTPService;
+class String8;
+struct HTTPBase;
+
+class PlayerServiceDataSourceFactory : public DataSourceFactory {
+public:
+    static sp<PlayerServiceDataSourceFactory> getInstance();
+    virtual sp<DataSource> CreateMediaHTTP(const sp<MediaHTTPService> &httpService);
+
+protected:
+    virtual sp<DataSource> CreateFileSource(const char *uri);
+
+private:
+    static sp<PlayerServiceDataSourceFactory> sInstance;
+    static Mutex sInstanceLock;
+    PlayerServiceDataSourceFactory() {};
+};
+
+}  // namespace android
+
+#endif  // PLAYER_SERVICE_DATA_SOURCE_FACTORY_H_
diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
new file mode 100644
index 0000000..08a013e
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceFileSource.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2009 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 PLAYER_SERVICE_FILE_SOURCE_H_
+
+#define PLAYER_SERVICE_FILE_SOURCE_H_
+
+#include <stdio.h>
+
+#include <datasource/FileSource.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/threads.h>
+#include <drm/DrmManagerClient.h>
+
+namespace android {
+
+// FileSource implementation which works on MediaPlayerService.
+// Supports OMA(forword-lock) files.
+class PlayerServiceFileSource : public FileSource {
+public:
+    PlayerServiceFileSource(const char *filename);
+    // PlayerServiceFileSource takes ownership and will close the fd
+    PlayerServiceFileSource(int fd, int64_t offset, int64_t length);
+
+    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+
+    virtual sp<DecryptHandle> DrmInitialization(const char *mime);
+
+    static bool requiresDrm(int fd, int64_t offset, int64_t length, const char *mime);
+
+protected:
+    virtual ~PlayerServiceFileSource();
+
+private:
+    /*for DRM*/
+    sp<DecryptHandle> mDecryptHandle;
+    DrmManagerClient *mDrmManagerClient;
+    int64_t mDrmBufOffset;
+    ssize_t mDrmBufSize;
+    unsigned char *mDrmBuf;
+
+    ssize_t readAtDRM_l(off64_t offset, void *data, size_t size);
+
+    PlayerServiceFileSource(const PlayerServiceFileSource &);
+    PlayerServiceFileSource &operator=(const PlayerServiceFileSource &);
+};
+
+}  // namespace android
+
+#endif  // PLAYER_SERVICE_FILE_SOURCE_H_
+
diff --git a/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
new file mode 100644
index 0000000..0032cd7
--- /dev/null
+++ b/media/libmediaplayerservice/datasource/include/datasource/PlayerServiceMediaHTTP.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2013 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 PLAYER_SERVICE_MEDIA_HTTP_H_
+
+#define PLAYER_SERVICE_MEDIA_HTTP_H_
+
+#include <datasource/MediaHTTP.h>
+#include <media/stagefright/foundation/AString.h>
+
+namespace android {
+
+struct MediaHTTPConnection;
+
+// MediaHTTP implementation which works on MediaPlayerService.
+// Supports OMA(forword-lock) stream.
+struct PlayerServiceMediaHTTP : public MediaHTTP {
+    PlayerServiceMediaHTTP(const sp<MediaHTTPConnection> &conn);
+
+protected:
+    virtual ~PlayerServiceMediaHTTP();
+
+    virtual sp<DecryptHandle> DrmInitialization(const char* mime);
+
+private:
+    sp<DecryptHandle> mDecryptHandle;
+    DrmManagerClient *mDrmManagerClient;
+
+    void clearDRMState_l();
+
+    DISALLOW_EVIL_CONSTRUCTORS(PlayerServiceMediaHTTP);
+};
+
+}  // namespace android
+
+#endif  // PLAYER_SERVICE_MEDIA_HTTP_H_
diff --git a/media/libmediaplayerservice/nuplayer/Android.bp b/media/libmediaplayerservice/nuplayer/Android.bp
index 19c8e76..c8f48a2 100644
--- a/media/libmediaplayerservice/nuplayer/Android.bp
+++ b/media/libmediaplayerservice/nuplayer/Android.bp
@@ -54,6 +54,10 @@
         "libpowermanager",
     ],
 
+    static_libs: [
+        "libplayerservice_datasource",
+    ],
+
     name: "libstagefright_nuplayer",
 
     sanitize: {
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index e26f1e6..f17520a 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -23,8 +23,8 @@
 #include "AnotherPacketSource.h"
 #include <binder/IServiceManager.h>
 #include <cutils/properties.h>
-#include <datasource/DataSourceFactory.h>
-#include <datasource/FileSource.h>
+#include <datasource/PlayerServiceDataSourceFactory.h>
+#include <datasource/PlayerServiceFileSource.h>
 #include <datasource/HTTPBase.h>
 #include <datasource/NuCachedSource2.h>
 #include <media/DataSource.h>
@@ -385,7 +385,8 @@
             if (!strncasecmp("http://", uri, 7) || !strncasecmp("https://", uri, 8)) {
                 sp<DataSource> httpSource;
                 mDisconnectLock.unlock();
-                httpSource = DataSourceFactory::CreateMediaHTTP(mHTTPService);
+                httpSource = PlayerServiceDataSourceFactory::getInstance()
+                        ->CreateMediaHTTP(mHTTPService);
                 if (httpSource == NULL) {
                     ALOGE("Failed to create http source!");
                     notifyPreparedAndCleanup(UNKNOWN_ERROR);
@@ -401,9 +402,9 @@
             mLock.unlock();
             mDisconnectLock.unlock();
             // This might take long time if connection has some issue.
-            sp<DataSource> dataSource = DataSourceFactory::CreateFromURI(
-                   mHTTPService, uri, &mUriHeaders, &contentType,
-                   static_cast<HTTPBase *>(mHttpSource.get()));
+            sp<DataSource> dataSource = PlayerServiceDataSourceFactory::getInstance()
+                    ->CreateFromURI(mHTTPService, uri, &mUriHeaders, &contentType,
+                            static_cast<HTTPBase *>(mHttpSource.get()));
             mDisconnectLock.lock();
             mLock.lock();
             if (!mDisconnected) {
@@ -411,7 +412,8 @@
             }
         } else {
             if (property_get_bool("media.stagefright.extractremote", true) &&
-                    !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
+                    !PlayerServiceFileSource::requiresDrm(
+                            mFd, mOffset, mLength, nullptr /* mime */)) {
                 sp<IBinder> binder =
                         defaultServiceManager()->getService(String16("media.extractor"));
                 if (binder != nullptr) {
@@ -438,7 +440,7 @@
             }
             if (mDataSource == nullptr) {
                 ALOGD("FileSource local");
-                mDataSource = new FileSource(mFd, mOffset, mLength);
+                mDataSource = new PlayerServiceFileSource(mFd, mOffset, mLength);
             }
             // TODO: close should always be done on mFd, see the lines following
             // CreateDataSourceFromIDataSource above,
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index a6dbce3..59cc24b 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -161,7 +161,6 @@
         "SimpleDecodingSource.cpp",
         "SkipCutBuffer.cpp",
         "StagefrightMediaScanner.cpp",
-        "StagefrightMetadataRetriever.cpp",
         "StagefrightPluginLoader.cpp",
         "SurfaceUtils.cpp",
         "ThrottledSource.cpp",
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index b89dcdf..66fb4b0 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -82,7 +82,7 @@
     }
 
     sp<DataSource> dataSource =
-        DataSourceFactory::CreateFromURI(httpService, path, headers);
+        DataSourceFactory::getInstance()->CreateFromURI(httpService, path, headers);
 
     if (dataSource == NULL) {
         return -ENOENT;
diff --git a/media/libstagefright/httplive/HTTPDownloader.cpp b/media/libstagefright/httplive/HTTPDownloader.cpp
index 7183dbd..68f1de9 100644
--- a/media/libstagefright/httplive/HTTPDownloader.cpp
+++ b/media/libstagefright/httplive/HTTPDownloader.cpp
@@ -21,8 +21,8 @@
 #include "HTTPDownloader.h"
 #include "M3UParser.h"
 
-#include <datasource/ClearMediaHTTP.h>
-#include <datasource/ClearFileSource.h>
+#include <datasource/MediaHTTP.h>
+#include <datasource/FileSource.h>
 #include <media/DataSource.h>
 #include <media/MediaHTTPConnection.h>
 #include <media/MediaHTTPService.h>
@@ -38,7 +38,7 @@
 HTTPDownloader::HTTPDownloader(
         const sp<MediaHTTPService> &httpService,
         const KeyedVector<String8, String8> &headers) :
-    mHTTPDataSource(new ClearMediaHTTP(httpService->makeHTTPConnection())),
+    mHTTPDataSource(new MediaHTTP(httpService->makeHTTPConnection())),
     mExtraHeaders(headers),
     mDisconnecting(false) {
 }
@@ -91,7 +91,7 @@
 
     if (reconnect) {
         if (!strncasecmp(url, "file://", 7)) {
-            mDataSource = new ClearFileSource(url + 7);
+            mDataSource = new FileSource(url + 7);
         } else if (strncasecmp(url, "http://", 7)
                 && strncasecmp(url, "https://", 8)) {
             return ERROR_UNSUPPORTED;
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index ee01d6c..6848a83 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -278,7 +278,7 @@
 
 static sp<IMediaExtractor> CreateExtractorFromURI(const char *uri) {
     sp<DataSource> source =
-        DataSourceFactory::CreateFromURI(NULL /* httpService */, uri);
+        DataSourceFactory::getInstance()->CreateFromURI(NULL /* httpService */, uri);
 
     if (source == NULL) {
         return NULL;
diff --git a/media/libstagefright/rtsp/SDPLoader.cpp b/media/libstagefright/rtsp/SDPLoader.cpp
index 5bd218d..e236267 100644
--- a/media/libstagefright/rtsp/SDPLoader.cpp
+++ b/media/libstagefright/rtsp/SDPLoader.cpp
@@ -22,7 +22,7 @@
 
 #include "ASessionDescription.h"
 
-#include <datasource/ClearMediaHTTP.h>
+#include <datasource/MediaHTTP.h>
 #include <media/MediaHTTPConnection.h>
 #include <media/MediaHTTPService.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -42,7 +42,7 @@
       mFlags(flags),
       mNetLooper(new ALooper),
       mCancelled(false),
-      mHTTPDataSource(new ClearMediaHTTP(httpService->makeHTTPConnection())) {
+      mHTTPDataSource(new MediaHTTP(httpService->makeHTTPConnection())) {
     mNetLooper->setName("sdp net");
     mNetLooper->start(false /* runOnCallingThread */,
                       false /* canCallJava */,
diff --git a/media/ndk/NdkMediaDataSource.cpp b/media/ndk/NdkMediaDataSource.cpp
index f6892e6..c1d4686 100644
--- a/media/ndk/NdkMediaDataSource.cpp
+++ b/media/ndk/NdkMediaDataSource.cpp
@@ -202,7 +202,7 @@
         headers.add(key8, value8);
     }
 
-    sp<DataSource> source = DataSourceFactory::CreateFromURI(service, uri, &headers);
+    sp<DataSource> source = DataSourceFactory::getInstance()->CreateFromURI(service, uri, &headers);
     if (source == NULL) {
         ALOGE("AMediaDataSource_newUri source is null");
         return NULL;
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
new file mode 100644
index 0000000..9db9c84
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/androidTest/java/com/android/media/benchmark/tests/EncoderTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package com.android.media.benchmark.tests;
+
+import android.content.Context;
+import android.media.MediaCodec;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.media.benchmark.R;
+import com.android.media.benchmark.library.CodecUtils;
+import com.android.media.benchmark.library.Decoder;
+import com.android.media.benchmark.library.Encoder;
+import com.android.media.benchmark.library.Extractor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.nio.ByteBuffer;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Parameterized.class)
+public class EncoderTest {
+    private static final Context mContext =
+            InstrumentationRegistry.getInstrumentation().getTargetContext();
+    private static final String mInputFilePath = mContext.getString(R.string.input_file_path);
+    private static final String mOutputFilePath = mContext.getString(R.string.output_file_path);
+    private static final String TAG = "EncoderTest";
+    private static final long PER_TEST_TIMEOUT_MS = 120000;
+    private static final boolean DEBUG = false;
+    private static final boolean WRITE_OUTPUT = false;
+    private static final int ENCODE_DEFAULT_FRAME_RATE = 25;
+    private static final int ENCODE_DEFAULT_BIT_RATE = 8000000 /* 8 Mbps */;
+    private static final int ENCODE_MIN_BIT_RATE = 600000 /* 600 Kbps */;
+
+    private String mInputFile;
+
+    @Parameterized.Parameters
+    public static Collection<Object[]> inputFiles() {
+        return Arrays.asList(new Object[][]{
+                // Audio Test
+                {"bbb_44100hz_2ch_128kbps_aac_30sec.mp4"},
+                {"bbb_8000hz_1ch_8kbps_amrnb_30sec.3gp"},
+                {"bbb_16000hz_1ch_9kbps_amrwb_30sec.3gp"},
+                {"bbb_44100hz_2ch_600kbps_flac_30sec.mp4"},
+                {"bbb_48000hz_2ch_100kbps_opus_30sec.webm"},
+                // Video Test
+                {"crowd_1920x1080_25fps_4000kbps_vp8.webm"},
+                {"crowd_1920x1080_25fps_6700kbps_h264.ts"},
+                {"crowd_1920x1080_25fps_4000kbps_h265.mkv"},
+                {"crowd_1920x1080_25fps_4000kbps_vp9.webm"},
+                {"crowd_176x144_25fps_6000kbps_mpeg4.mp4"},
+                {"crowd_176x144_25fps_6000kbps_h263.3gp"}});
+    }
+
+    public EncoderTest(String inputFileName) {
+        this.mInputFile = inputFileName;
+    }
+
+    @Test(timeout = PER_TEST_TIMEOUT_MS)
+    public void sampleEncoderTest() throws Exception {
+        int status;
+        int frameSize;
+
+        //Parameters for video
+        int width = 0;
+        int height = 0;
+        int profile = 0;
+        int level = 0;
+        int frameRate = 0;
+
+        //Parameters for audio
+        int bitRate = 0;
+        int sampleRate = 0;
+        int numChannels = 0;
+
+        File inputFile = new File(mInputFilePath + mInputFile);
+        if (inputFile.exists()) {
+            FileInputStream fileInput = new FileInputStream(inputFile);
+            FileDescriptor fileDescriptor = fileInput.getFD();
+            Extractor extractor = new Extractor();
+            int trackCount = extractor.setUpExtractor(fileDescriptor);
+            if (trackCount <= 0) {
+                Log.e(TAG, "Extraction failed. No tracks for file: " + mInputFile);
+                return;
+            }
+            ArrayList<ByteBuffer> inputBuffer = new ArrayList<>();
+            ArrayList<MediaCodec.BufferInfo> frameInfo = new ArrayList<>();
+            for (int currentTrack = 0; currentTrack < trackCount; currentTrack++) {
+                extractor.selectExtractorTrack(currentTrack);
+                MediaFormat format = extractor.getFormat(currentTrack);
+                // Get samples from extractor
+                int sampleSize;
+                do {
+                    sampleSize = extractor.getFrameSample();
+                    MediaCodec.BufferInfo bufInfo = new MediaCodec.BufferInfo();
+                    MediaCodec.BufferInfo info = extractor.getBufferInfo();
+                    ByteBuffer dataBuffer = ByteBuffer.allocate(info.size);
+                    dataBuffer.put(extractor.getFrameBuffer().array(), 0, info.size);
+                    bufInfo.set(info.offset, info.size, info.presentationTimeUs, info.flags);
+                    inputBuffer.add(dataBuffer);
+                    frameInfo.add(bufInfo);
+                    if (DEBUG) {
+                        Log.d(TAG, "Extracted bufInfo: flag = " + bufInfo.flags + " timestamp = " +
+                                bufInfo.presentationTimeUs + " size = " + bufInfo.size);
+                    }
+                } while (sampleSize > 0);
+
+                int tid = android.os.Process.myTid();
+                File decodedFile = new File(mContext.getFilesDir() + "/decoder_" + tid + ".out");
+                FileOutputStream decodeOutputStream = new FileOutputStream(decodedFile);
+                Decoder decoder = new Decoder();
+                decoder.setupDecoder(decodeOutputStream);
+                status = decoder.decode(inputBuffer, frameInfo, false, format, "");
+                if (status == 0) {
+                    Log.i(TAG, "Decoding complete.");
+                } else {
+                    Log.e(TAG, "Decode returned error. Encoding did not take place." + status);
+                    return;
+                }
+                decoder.deInitCodec();
+                extractor.unselectExtractorTrack(currentTrack);
+                inputBuffer.clear();
+                frameInfo.clear();
+                if (decodeOutputStream != null) {
+                    decodeOutputStream.close();
+                }
+                String mime = format.getString(MediaFormat.KEY_MIME);
+                ArrayList<String> mediaCodecs = CodecUtils.selectCodecs(mime, true);
+                if (mediaCodecs.size() <= 0) {
+                    Log.e(TAG, "No suitable codecs found for file: " + mInputFile + " track : " +
+                            currentTrack + " mime: " + mime);
+                    return;
+                }
+                Boolean[] encodeMode = {true, false};
+                /* Encoding the decoder's output */
+                for (Boolean asyncMode : encodeMode) {
+                    for (String codecName : mediaCodecs) {
+                        FileOutputStream encodeOutputStream = null;
+                        if (WRITE_OUTPUT) {
+                            File outEncodeFile = new File(mOutputFilePath + "encoder.out");
+                            if (outEncodeFile.exists()) {
+                                if (!outEncodeFile.delete()) {
+                                    Log.e(TAG, "Unable to delete existing file" +
+                                            decodedFile.toString());
+                                }
+                            }
+                            if (outEncodeFile.createNewFile()) {
+                                encodeOutputStream = new FileOutputStream(outEncodeFile);
+                            } else {
+                                Log.e(TAG, "Unable to create file to write encoder output: " +
+                                        outEncodeFile.toString());
+                            }
+                        }
+                        File rawFile =
+                                new File(mContext.getFilesDir() + "/decoder_" + tid + ".out");
+                        if (rawFile.exists()) {
+                            if (DEBUG) {
+                                Log.i(TAG, "Path of decoded input file: " + rawFile.toString());
+                            }
+                            FileInputStream eleStream = new FileInputStream(rawFile);
+                            if (mime.startsWith("video/")) {
+                                width = format.getInteger(MediaFormat.KEY_WIDTH);
+                                height = format.getInteger(MediaFormat.KEY_HEIGHT);
+                                if (format.containsKey(MediaFormat.KEY_FRAME_RATE)) {
+                                    frameRate = format.getInteger(MediaFormat.KEY_FRAME_RATE);
+                                } else if (frameRate <= 0) {
+                                    frameRate = ENCODE_DEFAULT_FRAME_RATE;
+                                }
+                                if (format.containsKey(MediaFormat.KEY_BIT_RATE)) {
+                                    bitRate = format.getInteger(MediaFormat.KEY_BIT_RATE);
+                                } else if (bitRate <= 0) {
+                                    if (mime.contains("video/3gpp") ||
+                                            mime.contains("video/mp4v-es")) {
+                                        bitRate = ENCODE_MIN_BIT_RATE;
+                                    } else {
+                                        bitRate = ENCODE_DEFAULT_BIT_RATE;
+                                    }
+                                }
+                                if (format.containsKey(MediaFormat.KEY_PROFILE)) {
+                                    profile = format.getInteger(MediaFormat.KEY_PROFILE);
+                                }
+                                if (format.containsKey(MediaFormat.KEY_PROFILE)) {
+                                    level = format.getInteger(MediaFormat.KEY_LEVEL);
+                                }
+                            } else {
+                                sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+                                numChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+                                bitRate = sampleRate * numChannels * 16;
+                            }
+                            /*Setup Encode Format*/
+                            MediaFormat encodeFormat;
+                            if (mime.startsWith("video/")) {
+                                frameSize = width * height * 3 / 2;
+                                encodeFormat = MediaFormat.createVideoFormat(mime, width, height);
+                                encodeFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
+                                encodeFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
+                                encodeFormat.setInteger(MediaFormat.KEY_PROFILE, profile);
+                                encodeFormat.setInteger(MediaFormat.KEY_LEVEL, level);
+                                encodeFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
+                                encodeFormat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, frameSize);
+                            } else {
+                                encodeFormat = MediaFormat
+                                        .createAudioFormat(mime, sampleRate, numChannels);
+                                encodeFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
+                                frameSize = 4096;
+                            }
+                            Encoder encoder = new Encoder();
+                            encoder.setupEncoder(encodeOutputStream, eleStream);
+                            status = encoder.encode(codecName, encodeFormat, mime, frameRate,
+                                    sampleRate, frameSize, asyncMode);
+                            encoder.deInitEncoder();
+                            if (status == 0) {
+                                encoder.dumpStatistics(mInputFile + "with " + codecName + " for " +
+                                        "aSyncMode = " + asyncMode, extractor.getClipDuration());
+                                Log.i(TAG, "Encoding complete for file: " + mInputFile +
+                                        " with codec: " + codecName + " for aSyncMode = " +
+                                        asyncMode);
+                            } else {
+                                Log.e(TAG,
+                                        codecName + " encoder returned error " + status + " for " +
+                                                "file:" + " " + mInputFile);
+                            }
+                            encoder.resetEncoder();
+                            eleStream.close();
+                            if (encodeOutputStream != null) {
+                                encodeOutputStream.close();
+                            }
+                        }
+                    }
+                }
+                //Cleanup temporary input file
+                if (decodedFile.exists()) {
+                    if (decodedFile.delete()) {
+                        Log.i(TAG, "Successfully deleted decoded file");
+                    } else {
+                        Log.e(TAG, "Unable to delete decoded file");
+                    }
+                }
+            }
+            extractor.deinitExtractor();
+            fileInput.close();
+        } else {
+            Log.w(TAG, "Warning: Test Skipped. Cannot find " + mInputFile + " in directory " +
+                    mInputFilePath);
+        }
+    }
+}
diff --git a/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
new file mode 100644
index 0000000..03db294
--- /dev/null
+++ b/media/tests/benchmark/MediaBenchmarkTest/src/main/java/com/android/media/benchmark/library/Encoder.java
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package com.android.media.benchmark.library;
+
+import android.media.MediaCodec;
+import android.media.MediaCodec.CodecException;
+import android.media.MediaFormat;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+public class Encoder {
+    private static final int ENCODE_DEFAULT_MAX_INPUT_SIZE = 3840;
+    private static final String TAG = "Encoder";
+    private static final boolean DEBUG = false;
+    private static final int kQueueDequeueTimeoutUs = 1000;
+
+    private final Object mLock = new Object();
+    private MediaCodec mCodec;
+    private String mMime;
+    private Stats mStats;
+
+    private int mOffset;
+    private int mFrameSize;
+    private int mNumInputFrame;
+    private int mNumFrames;
+    private int mFrameRate;
+    private int mSampleRate;
+    private long mInputBufferSize;
+
+    private boolean mSawInputEOS;
+    private boolean mSawOutputEOS;
+    private boolean mSignalledError;
+
+    private FileInputStream mInputStream;
+    private FileOutputStream mOutputStream;
+
+    public Encoder() {
+        mStats = new Stats();
+        mNumInputFrame = 0;
+        mSawInputEOS = false;
+        mSawOutputEOS = false;
+        mSignalledError = false;
+    }
+
+    /**
+     * Setup of encoder
+     *
+     * @param encoderOutputStream Will dump the encoder output in this stream if not null.
+     * @param fileInputStream     Will read the decoded output from this stream
+     */
+    public void setupEncoder(FileOutputStream encoderOutputStream,
+                             FileInputStream fileInputStream) {
+        this.mInputStream = fileInputStream;
+        this.mOutputStream = encoderOutputStream;
+    }
+
+    private MediaCodec createCodec(String codecName, String mime) throws IOException {
+        try {
+            MediaCodec codec;
+            if (codecName.isEmpty()) {
+                Log.i(TAG, "Mime type: " + mime);
+                if (mime != null) {
+                    codec = MediaCodec.createEncoderByType(mime);
+                    Log.i(TAG, "Encoder created for mime type " + mime);
+                    return codec;
+                } else {
+                    Log.e(TAG, "Mime type is null, please specify a mime type to create encoder");
+                    return null;
+                }
+            } else {
+                codec = MediaCodec.createByCodecName(codecName);
+                Log.i(TAG, "Encoder created with codec name: " + codecName + " and mime: " + mime);
+                return codec;
+            }
+        } catch (IllegalArgumentException ex) {
+            ex.printStackTrace();
+            Log.e(TAG, "Failed to create encoder for " + codecName + " mime: " + mime);
+            return null;
+        }
+    }
+
+    /**
+     * Encodes the given raw input file and measures the performance of encode operation,
+     * provided a valid list of parameters are passed as inputs.
+     *
+     * @param codecName    Will create the encoder with codecName
+     * @param mime         For creating encode format
+     * @param encodeFormat Format of the output data
+     * @param frameSize    Size of the frame
+     * @param asyncMode    Will run on async implementation if true
+     * @return 0 if encode was successful , -1 for fail, -2 for encoder not created
+     * @throws IOException If the codec cannot be created.
+     */
+    public int encode(String codecName, MediaFormat encodeFormat, String mime, int frameRate,
+                      int sampleRate, int frameSize, boolean asyncMode) throws IOException {
+        mInputBufferSize = mInputStream.getChannel().size();
+        mMime = mime;
+        mOffset = 0;
+        mFrameRate = frameRate;
+        mSampleRate = sampleRate;
+        long sTime = mStats.getCurTime();
+        mCodec = createCodec(codecName, mime);
+        if (mCodec == null) {
+            return -2;
+        }
+        /*Configure Codec*/
+        try {
+            mCodec.configure(encodeFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
+        } catch (IllegalArgumentException | IllegalStateException | MediaCodec.CryptoException e) {
+            Log.e(TAG, "Failed to configure " + mCodec.getName() + " encoder.");
+            e.printStackTrace();
+            return -2;
+        }
+        if (mMime.startsWith("video/")) {
+            mFrameSize = frameSize;
+        } else {
+            int maxInputSize = ENCODE_DEFAULT_MAX_INPUT_SIZE;
+            MediaFormat format = mCodec.getInputFormat();
+            if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
+                maxInputSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
+            }
+            mFrameSize = frameSize;
+            if (mFrameSize > maxInputSize && maxInputSize > 0) {
+                mFrameSize = maxInputSize;
+            }
+        }
+        mNumFrames = (int) ((mInputBufferSize + mFrameSize - 1) / mFrameSize);
+        if (asyncMode) {
+            mCodec.setCallback(new MediaCodec.Callback() {
+                @Override
+                public void onInputBufferAvailable(@NonNull MediaCodec mediaCodec,
+                                                   int inputBufferId) {
+                    try {
+                        mStats.addInputTime();
+                        onInputAvailable(mediaCodec, inputBufferId);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        Log.e(TAG, e.toString());
+                    }
+                }
+
+                @Override
+                public void onOutputBufferAvailable(@NonNull MediaCodec mediaCodec,
+                                                    int outputBufferId,
+                                                    @NonNull MediaCodec.BufferInfo bufferInfo) {
+                    mStats.addOutputTime();
+                    onOutputAvailable(mediaCodec, outputBufferId, bufferInfo);
+                    if (mSawOutputEOS) {
+                        Log.i(TAG, "Saw output EOS");
+                        synchronized (mLock) { mLock.notify(); }
+                    }
+                }
+
+                @Override
+                public void onError(@NonNull MediaCodec mediaCodec, @NonNull CodecException e) {
+                    mediaCodec.stop();
+                    mediaCodec.release();
+                    Log.e(TAG, "CodecError: " + e.toString());
+                    e.printStackTrace();
+                }
+
+                @Override
+                public void onOutputFormatChanged(@NonNull MediaCodec mediaCodec,
+                                                  @NonNull MediaFormat format) {
+                    Log.i(TAG, "Output format changed. Format: " + format.toString());
+                }
+            });
+        }
+        mCodec.start();
+        long eTime = mStats.getCurTime();
+        mStats.setInitTime(mStats.getTimeDiff(sTime, eTime));
+        mStats.setStartTime();
+        if (asyncMode) {
+            try {
+                synchronized (mLock) { mLock.wait(); }
+                if (mSignalledError) {
+                    return -1;
+                }
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+        } else {
+            while (!mSawOutputEOS && !mSignalledError) {
+                /* Queue input data */
+                if (!mSawInputEOS) {
+                    int inputBufferId = mCodec.dequeueInputBuffer(kQueueDequeueTimeoutUs);
+                    if (inputBufferId < 0 && inputBufferId != MediaCodec.INFO_TRY_AGAIN_LATER) {
+                        Log.e(TAG, "MediaCodec.dequeueInputBuffer " + "returned invalid index : " +
+                                inputBufferId);
+                        return -1;
+                    }
+                    mStats.addInputTime();
+                    onInputAvailable(mCodec, inputBufferId);
+                }
+                /* Dequeue output data */
+                MediaCodec.BufferInfo outputBufferInfo = new MediaCodec.BufferInfo();
+                int outputBufferId =
+                        mCodec.dequeueOutputBuffer(outputBufferInfo, kQueueDequeueTimeoutUs);
+                if (outputBufferId < 0) {
+                    if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                        MediaFormat outFormat = mCodec.getOutputFormat();
+                        Log.i(TAG, "Output format changed. Format: " + outFormat.toString());
+                    } else if (outputBufferId != MediaCodec.INFO_TRY_AGAIN_LATER) {
+                        Log.e(TAG, "MediaCodec.dequeueOutputBuffer" + " returned invalid index " +
+                                outputBufferId);
+                        return -1;
+                    }
+                } else {
+                    mStats.addOutputTime();
+                    if (DEBUG) {
+                        Log.d(TAG, "Dequeue O/P buffer with BufferID " + outputBufferId);
+                    }
+                    onOutputAvailable(mCodec, outputBufferId, outputBufferInfo);
+                }
+            }
+        }
+        return 0;
+    }
+
+    private void onOutputAvailable(MediaCodec mediaCodec, int outputBufferId,
+                                   MediaCodec.BufferInfo outputBufferInfo) {
+        if (mSawOutputEOS || outputBufferId < 0) {
+            if (mSawOutputEOS) {
+                Log.i(TAG, "Saw output EOS");
+            }
+            return;
+        }
+        ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputBufferId);
+        if (mOutputStream != null) {
+            try {
+
+                byte[] bytesOutput = new byte[outputBuffer.remaining()];
+                outputBuffer.get(bytesOutput);
+                mOutputStream.write(bytesOutput);
+            } catch (IOException e) {
+                e.printStackTrace();
+                Log.d(TAG, "Error Dumping File: Exception " + e.toString());
+                return;
+            }
+        }
+        mStats.addFrameSize(outputBuffer.remaining());
+        mediaCodec.releaseOutputBuffer(outputBufferId, false);
+        mSawOutputEOS = (outputBufferInfo.flags == MediaCodec.BUFFER_FLAG_END_OF_STREAM);
+    }
+
+    private void onInputAvailable(MediaCodec mediaCodec, int inputBufferId) throws IOException {
+        if (mSawOutputEOS || inputBufferId < 0) {
+            if (mSawOutputEOS) {
+                Log.i(TAG, "Saw input EOS");
+            }
+            return;
+        }
+        if (mInputBufferSize < mOffset) {
+            Log.e(TAG, "Out of bound access of input buffer");
+            mSignalledError = true;
+            return;
+        }
+        ByteBuffer inputBuffer = mCodec.getInputBuffer(inputBufferId);
+        if (inputBuffer == null) {
+            mSignalledError = true;
+            return;
+        }
+        int bufSize = inputBuffer.capacity();
+        int bytesRead = mFrameSize;
+        if (mInputBufferSize - mOffset < mFrameSize) {
+            bytesRead = (int) (mInputBufferSize - mOffset);
+        }
+        if (bufSize < bytesRead) {
+            mSignalledError = true;
+            return;
+        }
+        byte[] inputArray = new byte[bytesRead];
+        mInputStream.read(inputArray, 0, bytesRead);
+        inputBuffer.put(inputArray);
+        int flag = 0;
+        if (mNumInputFrame >= mNumFrames - 1 || bytesRead == 0) {
+            Log.i(TAG, "Sending EOS on input last frame");
+            mSawInputEOS = true;
+            flag = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
+        }
+        int presentationTimeUs;
+        if (mMime.startsWith("video/")) {
+            presentationTimeUs = mNumInputFrame * (1000000 / mFrameRate);
+        } else {
+            presentationTimeUs = mNumInputFrame * mFrameSize * 1000000 / mSampleRate;
+        }
+        mediaCodec.queueInputBuffer(inputBufferId, 0, bytesRead, presentationTimeUs, flag);
+        mNumInputFrame++;
+        mOffset += bytesRead;
+    }
+
+    /**
+     * Stops the codec and releases codec resources.
+     */
+    public void deInitEncoder() {
+        long sTime = mStats.getCurTime();
+        if (mCodec != null) {
+            mCodec.stop();
+            mCodec.release();
+            mCodec = null;
+        }
+        long eTime = mStats.getCurTime();
+        mStats.setDeInitTime(mStats.getTimeDiff(sTime, eTime));
+    }
+
+    /**
+     * Prints out the statistics in the information log
+     *
+     * @param inputReference The operation being performed, in this case encode
+     * @param durationUs     Duration of the clip in microseconds
+     */
+    public void dumpStatistics(String inputReference, long durationUs) {
+        String operation = "encode";
+        mStats.dumpStatistics(operation, inputReference, durationUs);
+    }
+
+    /**
+     * Resets the stats
+     */
+    public void resetEncoder() {
+        mOffset = 0;
+        mInputBufferSize = 0;
+        mNumInputFrame = 0;
+        mSawInputEOS = false;
+        mSawOutputEOS = false;
+        mSignalledError = false;
+        mStats.reset();
+    }
+}
diff --git a/media/tests/benchmark/README.md b/media/tests/benchmark/README.md
index 1c1ef4f..487ddb8 100644
--- a/media/tests/benchmark/README.md
+++ b/media/tests/benchmark/README.md
@@ -99,7 +99,6 @@
 adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.ExtractorTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
 ```
 
-
 ## Decoder
 
 The test decodes input stream and benchmarks the decoders available in SDK.
@@ -107,11 +106,17 @@
 adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.DecoderTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
 ```
 
-
 ## Muxer
 
 The test muxes elementary stream and benchmarks different writers available in SDK.
 ```
 adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.MuxerTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
+```
+
+## Encoder
+
+The test encodes input stream and benchmarks the encoders available in SDK.
+```
+adb shell am instrument -w -r -e class 'com.android.media.benchmark.tests.EncoderTest' com.android.media.benchmark/androidx.test.runner.AndroidJUnitRunner
 
 ```
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index ac6b771..6239fb2 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -55,7 +55,7 @@
 
 sp<IDataSource> MediaExtractorService::makeIDataSource(int fd, int64_t offset, int64_t length)
 {
-    sp<DataSource> source = DataSourceFactory::CreateFromFd(fd, offset, length);
+    sp<DataSource> source = DataSourceFactory::getInstance()->CreateFromFd(fd, offset, length);
     return CreateIDataSourceFromDataSource(source);
 }