Remove IDataSource dependency from DataSource.

The logic for requesting file data source to media extractor service
moved to MediaExtractorFactory from GenericSource.

Bug: 65851881, Bug: 63934228
Test: MediaCts post commit tests
Change-Id: Iaba6d9bec560f0cd8a826f47d74bf491a34c83e9
diff --git a/media/libmedia/nuplayer2/GenericSource.cpp b/media/libmedia/nuplayer2/GenericSource.cpp
index 900c78b..6f78b6b 100644
--- a/media/libmedia/nuplayer2/GenericSource.cpp
+++ b/media/libmedia/nuplayer2/GenericSource.cpp
@@ -162,15 +162,30 @@
 
 status_t NuPlayer2::GenericSource::initFromDataSource() {
     sp<IMediaExtractor> extractor;
-    CHECK(mDataSource != NULL);
+    CHECK(mDataSource != NULL || mFd != -1);
     sp<DataSource> dataSource = mDataSource;
+    const int fd = mFd;
+    const int64_t offset = mOffset;
+    const int64_t length = mLength;
 
     mLock.unlock();
     // This might take long time if data source is not reliable.
-    extractor = MediaExtractorFactory::Create(dataSource, NULL);
+    if (dataSource != nullptr) {
+        extractor = MediaExtractorFactory::Create(dataSource, NULL /* mime */);
+    } else {
+        extractor = MediaExtractorFactory::CreateFromFd(
+                fd, offset, length, NULL /* mime */, &dataSource);
+    }
+
+    if (dataSource == nullptr) {
+        ALOGE("initFromDataSource, failed to create data source!");
+        mLock.lock();
+        return UNKNOWN_ERROR;
+    }
 
     if (extractor == NULL) {
         ALOGE("initFromDataSource, cannot create extractor!");
+        mLock.lock();
         return UNKNOWN_ERROR;
     }
 
@@ -179,10 +194,13 @@
     size_t numtracks = extractor->countTracks();
     if (numtracks == 0) {
         ALOGE("initFromDataSource, source has no track!");
+        mLock.lock();
         return UNKNOWN_ERROR;
     }
 
     mLock.lock();
+    mFd = -1;
+    mDataSource = dataSource;
     mFileMeta = fileMeta;
     if (mFileMeta != NULL) {
         int64_t duration;
@@ -395,51 +413,16 @@
             if (!mDisconnected) {
                 mDataSource = dataSource;
             }
-        } else {
-            if (property_get_bool("media.stagefright.extractremote", true) &&
-                    !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
-                sp<IBinder> binder =
-                        defaultServiceManager()->getService(String16("media.extractor"));
-                if (binder != nullptr) {
-                    ALOGD("FileSource remote");
-                    sp<IMediaExtractorService> mediaExService(
-                            interface_cast<IMediaExtractorService>(binder));
-                    sp<IDataSource> source =
-                            mediaExService->makeIDataSource(mFd, mOffset, mLength);
-                    ALOGV("IDataSource(FileSource): %p %d %lld %lld",
-                            source.get(), mFd, (long long)mOffset, (long long)mLength);
-                    if (source.get() != nullptr) {
-                        mDataSource = CreateDataSourceFromIDataSource(source);
-                        if (mDataSource != nullptr) {
-                            // Close the local file descriptor as it is not needed anymore.
-                            close(mFd);
-                            mFd = -1;
-                        }
-                    } else {
-                        ALOGW("extractor service cannot make data source");
-                    }
-                } else {
-                    ALOGW("extractor service not running");
-                }
-            }
-            if (mDataSource == nullptr) {
-                ALOGD("FileSource local");
-                mDataSource = new FileSource(mFd, mOffset, mLength);
-            }
-            // TODO: close should always be done on mFd, see the lines following
-            // CreateDataSourceFromIDataSource above,
-            // and the FileSource constructor should dup the mFd argument as needed.
-            mFd = -1;
         }
 
-        if (mDataSource == NULL) {
+        if (mFd == -1 && mDataSource == NULL) {
             ALOGE("Failed to create data source!");
             notifyPreparedAndCleanup(UNKNOWN_ERROR);
             return;
         }
     }
 
-    if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
+    if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
         mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
     }
 
diff --git a/media/libmediaextractor/DataSource.cpp b/media/libmediaextractor/DataSource.cpp
index c22e4cb..72959c6 100644
--- a/media/libmediaextractor/DataSource.cpp
+++ b/media/libmediaextractor/DataSource.cpp
@@ -17,7 +17,6 @@
 #define LOG_TAG "DataSource"
 
 #include <media/DataSource.h>
-#include <media/IDataSource.h>
 #include <media/stagefright/foundation/ByteUtils.h>
 #include <media/stagefright/MediaErrors.h>
 #include <utils/String8.h>
@@ -124,10 +123,6 @@
     return ERROR_UNSUPPORTED;
 }
 
-sp<IDataSource> DataSource::getIDataSource() const {
-    return nullptr;
-}
-
 String8 DataSource::getMIMEType() const {
     return String8("application/octet-stream");
 }
diff --git a/media/libmediaextractor/include/media/DataSource.h b/media/libmediaextractor/include/media/DataSource.h
index e917f4e..0b4bc27 100644
--- a/media/libmediaextractor/include/media/DataSource.h
+++ b/media/libmediaextractor/include/media/DataSource.h
@@ -112,9 +112,6 @@
 
     virtual void close() {};
 
-    // returns a pointer to IDataSource if it is wrapped.
-    virtual sp<IDataSource> getIDataSource() const;
-
 protected:
     virtual ~DataSource() {}
 
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
index a3f4efb..cbbf34d 100644
--- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp
@@ -26,7 +26,6 @@
 #include <media/DataSource.h>
 #include <media/MediaExtractor.h>
 #include <media/MediaSource.h>
-#include <media/IMediaExtractorService.h>
 #include <media/IMediaHTTPService.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -161,15 +160,30 @@
 
 status_t NuPlayer::GenericSource::initFromDataSource() {
     sp<IMediaExtractor> extractor;
-    CHECK(mDataSource != NULL);
+    CHECK(mDataSource != NULL || mFd != -1);
     sp<DataSource> dataSource = mDataSource;
+    const int fd = mFd;
+    const int64_t offset = mOffset;
+    const int64_t length = mLength;
 
     mLock.unlock();
     // This might take long time if data source is not reliable.
-    extractor = MediaExtractorFactory::Create(dataSource, NULL);
+    if (dataSource != nullptr) {
+        extractor = MediaExtractorFactory::Create(dataSource, NULL /* mime */);
+    } else {
+        extractor = MediaExtractorFactory::CreateFromFd(
+                fd, offset, length, NULL /* mime */, &dataSource);
+    }
+
+    if (dataSource == nullptr) {
+        ALOGE("initFromDataSource, failed to create data source!");
+        mLock.lock();
+        return UNKNOWN_ERROR;
+    }
 
     if (extractor == NULL) {
         ALOGE("initFromDataSource, cannot create extractor!");
+        mLock.lock();
         return UNKNOWN_ERROR;
     }
 
@@ -178,10 +192,13 @@
     size_t numtracks = extractor->countTracks();
     if (numtracks == 0) {
         ALOGE("initFromDataSource, source has no track!");
+        mLock.lock();
         return UNKNOWN_ERROR;
     }
 
     mLock.lock();
+    mFd = -1;
+    mDataSource = dataSource;
     mFileMeta = fileMeta;
     if (mFileMeta != NULL) {
         int64_t duration;
@@ -394,51 +411,15 @@
             if (!mDisconnected) {
                 mDataSource = dataSource;
             }
-        } else {
-            if (property_get_bool("media.stagefright.extractremote", true) &&
-                    !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
-                sp<IBinder> binder =
-                        defaultServiceManager()->getService(String16("media.extractor"));
-                if (binder != nullptr) {
-                    ALOGD("FileSource remote");
-                    sp<IMediaExtractorService> mediaExService(
-                            interface_cast<IMediaExtractorService>(binder));
-                    sp<IDataSource> source =
-                            mediaExService->makeIDataSource(mFd, mOffset, mLength);
-                    ALOGV("IDataSource(FileSource): %p %d %lld %lld",
-                            source.get(), mFd, (long long)mOffset, (long long)mLength);
-                    if (source.get() != nullptr) {
-                        mDataSource = CreateDataSourceFromIDataSource(source);
-                        if (mDataSource != nullptr) {
-                            // Close the local file descriptor as it is not needed anymore.
-                            close(mFd);
-                            mFd = -1;
-                        }
-                    } else {
-                        ALOGW("extractor service cannot make data source");
-                    }
-                } else {
-                    ALOGW("extractor service not running");
-                }
-            }
-            if (mDataSource == nullptr) {
-                ALOGD("FileSource local");
-                mDataSource = new FileSource(mFd, mOffset, mLength);
-            }
-            // TODO: close should always be done on mFd, see the lines following
-            // CreateDataSourceFromIDataSource above,
-            // and the FileSource constructor should dup the mFd argument as needed.
-            mFd = -1;
         }
-
-        if (mDataSource == NULL) {
+        if (mFd == -1 && mDataSource == NULL) {
             ALOGE("Failed to create data source!");
             notifyPreparedAndCleanup(UNKNOWN_ERROR);
             return;
         }
     }
 
-    if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
+    if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
         mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
     }
 
diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp
index 6dfe2de..f479644 100644
--- a/media/libstagefright/CallbackDataSource.cpp
+++ b/media/libstagefright/CallbackDataSource.cpp
@@ -113,10 +113,6 @@
     return mIDataSource->DrmInitialization(mime);
 }
 
-sp<IDataSource> CallbackDataSource::getIDataSource() const {
-    return mIDataSource;
-}
-
 TinyCacheSource::TinyCacheSource(const sp<DataSource>& source)
     : mSource(source), mCachedOffset(0), mCachedSize(0) {
     mName = String8::format("TinyCacheSource(%s)", mSource->toString().string());
@@ -194,8 +190,4 @@
     return mSource->DrmInitialization(mime);
 }
 
-sp<IDataSource> TinyCacheSource::getIDataSource() const {
-    return mSource->getIDataSource();
-}
-
 } // namespace android
diff --git a/media/libstagefright/MediaExtractorFactory.cpp b/media/libstagefright/MediaExtractorFactory.cpp
index 1b12510..e1e04eb 100644
--- a/media/libstagefright/MediaExtractorFactory.cpp
+++ b/media/libstagefright/MediaExtractorFactory.cpp
@@ -23,6 +23,7 @@
 #include <media/MediaAnalyticsItem.h>
 #include <media/MediaExtractor.h>
 #include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/FileSource.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/MediaExtractorFactory.h>
 #include <media/stagefright/MetaData.h>
@@ -44,7 +45,7 @@
 // static
 sp<IMediaExtractor> MediaExtractorFactory::Create(
         const sp<DataSource> &source, const char *mime) {
-    ALOGV("MediaExtractorFactory::Create %s", mime);
+    ALOGV("MediaExtractorFactory::%s %s", __func__, mime);
 
     if (!property_get_bool("media.stagefright.extractremote", true)) {
         // local extractor
@@ -69,10 +70,48 @@
     return NULL;
 }
 
+// static
+sp<IMediaExtractor> MediaExtractorFactory::CreateFromFd(
+        int fd, int64_t offset, int64_t length, const char *mime, sp<DataSource> *out) {
+    ALOGV("MediaExtractorFactory::%s %s", __func__, mime);
+
+    if (property_get_bool("media.stagefright.extractremote", true)) {
+        // remote extractor
+        ALOGV("get service manager");
+        sp<IBinder> binder = defaultServiceManager()->getService(String16("media.extractor"));
+
+        if (binder != 0) {
+            sp<IMediaExtractorService> mediaExService(
+                    interface_cast<IMediaExtractorService>(binder));
+            if (!FileSource::requiresDrm(fd, offset, length, nullptr /* mime */)) {
+                ALOGD("FileSource remote");
+                sp<IDataSource> remoteSource =
+                    mediaExService->makeIDataSource(fd, offset, length);
+                ALOGV("IDataSource(FileSource): %p %d %lld %lld",
+                        remoteSource.get(), fd, (long long)offset, (long long)length);
+                if (remoteSource.get() != nullptr) {
+                    // replace the caller's local source with remote source.
+                    *out = CreateDataSourceFromIDataSource(remoteSource);
+                    return mediaExService->makeExtractor(remoteSource, mime);
+                } else {
+                    ALOGW("extractor service cannot make file source."
+                            " falling back to local file source.");
+                }
+            }
+            // Falls back.
+        } else {
+            ALOGE("extractor service not running");
+            return nullptr;
+        }
+    }
+    *out = new FileSource(fd, offset, length);
+    return Create(*out, mime);
+}
+
 sp<MediaExtractor> MediaExtractorFactory::CreateFromService(
         const sp<DataSource> &source, const char *mime) {
 
-    ALOGV("MediaExtractorFactory::CreateFromService %s", mime);
+    ALOGV("MediaExtractorFactory::%s %s", __func__, mime);
     RegisterDefaultSniffers();
 
     // initialize source decryption if needed
diff --git a/media/libstagefright/include/CallbackDataSource.h b/media/libstagefright/include/CallbackDataSource.h
index 9f413cd..32556d6 100644
--- a/media/libstagefright/include/CallbackDataSource.h
+++ b/media/libstagefright/include/CallbackDataSource.h
@@ -42,7 +42,6 @@
         return mName;
     }
     virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
-    virtual sp<IDataSource> getIDataSource() const;
 
 private:
     sp<IDataSource> mIDataSource;
@@ -71,7 +70,6 @@
         return mName;
     }
     virtual sp<DecryptHandle> DrmInitialization(const char *mime = NULL);
-    virtual sp<IDataSource> getIDataSource() const;
 
 private:
     // 2kb comes from experimenting with the time-to-first-frame from a MediaPlayer
diff --git a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
index 96298f9..f216ff8 100644
--- a/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
+++ b/media/libstagefright/include/media/stagefright/MediaExtractorFactory.h
@@ -31,6 +31,12 @@
 public:
     static sp<IMediaExtractor> Create(
             const sp<DataSource> &source, const char *mime = NULL);
+    // Creates media extractor from the given file descriptor. To avoid binder calls for
+    // reading file data, this tries to create remote file source in extractor service.
+    // If that fails, this falls back to local file source. The data source used for extractor
+    // will be alsp returned with |out|.
+    static sp<IMediaExtractor> CreateFromFd(
+            int fd, int64_t offset, int64_t length, const char *mime, sp<DataSource> *out);
     static sp<MediaExtractor> CreateFromService(
             const sp<DataSource> &source, const char *mime = NULL);
 
diff --git a/media/libstagefright/include/media/stagefright/RemoteDataSource.h b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
index e191e6a..4ddc5e3 100644
--- a/media/libstagefright/include/media/stagefright/RemoteDataSource.h
+++ b/media/libstagefright/include/media/stagefright/RemoteDataSource.h
@@ -31,9 +31,6 @@
         if (source.get() == nullptr) {
             return nullptr;
         }
-        if (source->getIDataSource().get() != nullptr) {
-            return source->getIDataSource();
-        }
         return new RemoteDataSource(source);
     }