Merge "MediaPlayer2: add native DataSourceDesc."
diff --git a/media/libmedia/Android.bp b/media/libmedia/Android.bp
index 1377005..3ac519b 100644
--- a/media/libmedia/Android.bp
+++ b/media/libmedia/Android.bp
@@ -254,6 +254,7 @@
 
     srcs: [
         "BufferingSettings.cpp",
+        "DataSourceDesc.cpp",
         "IDataSource.cpp",
         "IMediaExtractor.cpp",
         "IMediaExtractorService.cpp",
diff --git a/media/libmedia/DataSourceDesc.cpp b/media/libmedia/DataSourceDesc.cpp
new file mode 100644
index 0000000..b7ccbce
--- /dev/null
+++ b/media/libmedia/DataSourceDesc.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright 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 "DataSourceDesc"
+
+#include <media/DataSource.h>
+#include <media/DataSourceDesc.h>
+#include <media/MediaHTTPService.h>
+
+namespace android {
+
+static const int64_t kLongMax = 0x7ffffffffffffffL;
+
+DataSourceDesc::DataSourceDesc()
+    : mType(TYPE_NONE),
+      mFDOffset(0),
+      mFDLength(kLongMax),
+      mId(0),
+      mStartPositionMs(0),
+      mEndPositionMs(0) {
+}
+
+}  // namespace android
diff --git a/media/libmedia/MediaPlayer2Manager.cpp b/media/libmedia/MediaPlayer2Manager.cpp
index aefb91c..76b4c0b 100644
--- a/media/libmedia/MediaPlayer2Manager.cpp
+++ b/media/libmedia/MediaPlayer2Manager.cpp
@@ -45,6 +45,7 @@
 #include <utils/Vector.h>
 
 #include <media/AudioPolicyHelper.h>
+#include <media/DataSourceDesc.h>
 #include <media/MediaHTTPService.h>
 #include <media/MediaPlayer2EngineClient.h>
 #include <media/MediaPlayer2Interface.h>
@@ -247,13 +248,6 @@
 
 MediaPlayer2Manager gMediaPlayer2Manager;
 
-static bool checkPermission(const char* permissionString) {
-    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
-    bool ok = checkCallingPermission(String16(permissionString));
-    if (!ok) ALOGE("Request requires %s", permissionString);
-    return ok;
-}
-
 // TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
 /* static */ int MediaPlayer2Manager::AudioOutput::mMinBufferCount = 4;
 /* static */ bool MediaPlayer2Manager::AudioOutput::mIsOnEmulator = false;
@@ -284,6 +278,10 @@
     sp<Client> c = new Client(
             mPid, connId, client, audioSessionId, mUid);
 
+    if (!c->init()) {
+        return NULL;
+    }
+
     ALOGV("Create new client(%d) from pid %d, uid %d, ", connId, mPid, mUid);
 
     wp<Client> w = c;
@@ -514,6 +512,25 @@
 #endif
 }
 
+bool MediaPlayer2Manager::Client::init() {
+    sp<MediaPlayer2Interface> p = new NuPlayer2Driver(mPid);
+    status_t init_result = p->initCheck();
+    if (init_result != NO_ERROR) {
+        ALOGE("Failed to create player object, initCheck failed(%d)", init_result);
+        return false;
+    }
+
+    p->setNotifyCallback(this, notify);
+    p->setUID(mUid);
+    mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);
+    mAudioOutput = new AudioOutput(mAudioSessionId, mUid,
+            mPid, mAudioAttributes, mAudioDeviceUpdatedListener);
+    p->setAudioSink(mAudioOutput);
+
+    mPlayer = p;
+    return true;
+}
+
 MediaPlayer2Manager::Client::~Client()
 {
     ALOGV("Client(%d) destructor pid = %d", mConnId, mPid);
@@ -560,26 +577,6 @@
     IPCThreadState::self()->flushCommands();
 }
 
-sp<MediaPlayer2Interface> MediaPlayer2Manager::Client::createPlayer() {
-    sp<MediaPlayer2Interface> p = getPlayer();
-    if (p == NULL) {
-        p = new NuPlayer2Driver(mPid);
-        status_t init_result = p->initCheck();
-        if (init_result == NO_ERROR) {
-            p->setNotifyCallback(this, notify);
-        } else {
-            ALOGE("Failed to create player, initCheck failed(res = %d)", init_result);
-            p.clear();
-        }
-    }
-
-    if (p != NULL) {
-        p->setUID(mUid);
-    }
-
-    return p;
-}
-
 void MediaPlayer2Manager::Client::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate(
         audio_io_handle_t audioIo,
         audio_port_handle_t deviceId) {
@@ -591,30 +588,20 @@
     }
 }
 
-sp<MediaPlayer2Interface> MediaPlayer2Manager::Client::setDataSource_pre() {
-    sp<MediaPlayer2Interface> p = createPlayer();
+status_t MediaPlayer2Manager::Client::setDataSource(
+        const sp<DataSourceDesc> &dsd) {
+    sp<MediaPlayer2Interface> p = getPlayer();
     if (p == NULL) {
-        return p;
+        return NO_INIT;
     }
 
-    Mutex::Autolock lock(mLock);
+    if (dsd == NULL) {
+        return BAD_VALUE;
+    }
 
-    mAudioDeviceUpdatedListener = new AudioDeviceUpdatedNotifier(p);
-
-    mAudioOutput = new AudioOutput(mAudioSessionId, mUid,
-            mPid, mAudioAttributes, mAudioDeviceUpdatedListener);
-    p->setAudioSink(mAudioOutput);
-
-    return p;
-}
-
-status_t MediaPlayer2Manager::Client::setDataSource_post(
-        const sp<MediaPlayer2Interface>& p,
-        status_t status)
-{
-    ALOGV(" setDataSource");
+    status_t status = p->setDataSource(dsd);
     if (status != OK) {
-        ALOGE("  error: %d", status);
+        ALOGE("setDataSource error: %d", status);
         return status;
     }
 
@@ -626,102 +613,9 @@
         }
     }
 
-    if (status == OK) {
-        Mutex::Autolock lock(mLock);
-        mPlayer = p;
-    }
     return status;
 }
 
-status_t MediaPlayer2Manager::Client::setDataSource(
-        const sp<MediaHTTPService> &httpService,
-        const char *url,
-        const KeyedVector<String8, String8> *headers)
-{
-    ALOGV("setDataSource(%s)", url);
-    if (url == NULL)
-        return UNKNOWN_ERROR;
-
-    if ((strncmp(url, "http://", 7) == 0) ||
-        (strncmp(url, "https://", 8) == 0) ||
-        (strncmp(url, "rtsp://", 7) == 0)) {
-        if (!checkPermission("android.permission.INTERNET")) {
-            return PERMISSION_DENIED;
-        }
-    }
-
-    if (strncmp(url, "content://", 10) == 0) {
-        ALOGE("setDataSource: content scheme is not supported here");
-        mStatus = UNKNOWN_ERROR;
-        return mStatus;
-    } else {
-        sp<MediaPlayer2Interface> p = setDataSource_pre();
-        if (p == NULL) {
-            return NO_INIT;
-        }
-
-        return mStatus =
-                setDataSource_post(
-                p, p->setDataSource(httpService, url, headers));
-    }
-}
-
-status_t MediaPlayer2Manager::Client::setDataSource(int fd, int64_t offset, int64_t length)
-{
-    ALOGV("setDataSource fd=%d (%s), offset=%lld, length=%lld",
-            fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
-    struct stat sb;
-    int ret = fstat(fd, &sb);
-    if (ret != 0) {
-        ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
-        return UNKNOWN_ERROR;
-    }
-
-    ALOGV("st_dev  = %llu", static_cast<unsigned long long>(sb.st_dev));
-    ALOGV("st_mode = %u", sb.st_mode);
-    ALOGV("st_uid  = %lu", static_cast<unsigned long>(sb.st_uid));
-    ALOGV("st_gid  = %lu", static_cast<unsigned long>(sb.st_gid));
-    ALOGV("st_size = %llu", static_cast<unsigned long long>(sb.st_size));
-
-    if (offset >= sb.st_size) {
-        ALOGE("offset error");
-        return UNKNOWN_ERROR;
-    }
-    if (offset + length > sb.st_size) {
-        length = sb.st_size - offset;
-        ALOGV("calculated length = %lld", (long long)length);
-    }
-
-    sp<MediaPlayer2Interface> p = setDataSource_pre();
-    if (p == NULL) {
-        return NO_INIT;
-    }
-
-    // now set data source
-    return mStatus = setDataSource_post(p, p->setDataSource(fd, offset, length));
-}
-
-status_t MediaPlayer2Manager::Client::setDataSource(
-        const sp<IStreamSource> &source) {
-    sp<MediaPlayer2Interface> p = setDataSource_pre();
-    if (p == NULL) {
-        return NO_INIT;
-    }
-
-    // now set data source
-    return mStatus = setDataSource_post(p, p->setDataSource(source));
-}
-
-status_t MediaPlayer2Manager::Client::setDataSource(
-        const sp<DataSource> &source) {
-    sp<MediaPlayer2Interface> p = setDataSource_pre();
-    if (p == NULL) {
-        return NO_INIT;
-    }
-    // now set data source
-    return mStatus = setDataSource_post(p, p->setDataSource(source));
-}
-
 void MediaPlayer2Manager::Client::disconnectNativeWindow_l() {
     if (mConnectedWindow != NULL && mConnectedWindow->getANativeWindow() != NULL) {
         status_t err = native_window_api_disconnect(
@@ -1187,13 +1081,8 @@
         ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
     }
 
-    sp<MediaPlayer2Interface> p = getPlayer();
-
     // Right now, the only valid time to set a retransmit endpoint is before
-    // player selection has been made (since the presence or absence of a
-    // retransmit endpoint is going to determine which player is selected during
-    // setDataSource).
-    if (p != 0) return INVALID_OPERATION;
+    // setDataSource.
 
     if (NULL != endpoint) {
         Mutex::Autolock lock(mLock);
diff --git a/media/libmedia/MediaPlayer2Manager.h b/media/libmedia/MediaPlayer2Manager.h
index 20cc735..cdbbc70 100644
--- a/media/libmedia/MediaPlayer2Manager.h
+++ b/media/libmedia/MediaPlayer2Manager.h
@@ -287,22 +287,7 @@
                                         const sp<media::VolumeShaper::Operation>& operation) override;
         virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) override;
 
-        sp<MediaPlayer2Interface>    createPlayer();
-
-        virtual status_t        setDataSource(
-                        const sp<MediaHTTPService> &httpService,
-                        const char *url,
-                        const KeyedVector<String8, String8> *headers);
-
-        virtual status_t        setDataSource(int fd, int64_t offset, int64_t length);
-
-        virtual status_t        setDataSource(const sp<IStreamSource> &source);
-        virtual status_t        setDataSource(const sp<DataSource> &source);
-
-
-        sp<MediaPlayer2Interface>    setDataSource_pre();
-        status_t                setDataSource_post(const sp<MediaPlayer2Interface>& p,
-                                                   status_t status);
+        virtual status_t        setDataSource(const sp<DataSourceDesc> &dsd);
 
         static  void            notify(const wp<MediaPlayer2Engine> &listener, int msg,
                                        int ext1, int ext2, const Parcel *obj);
@@ -343,6 +328,7 @@
                                        uid_t uid);
                                 Client();
         virtual                 ~Client();
+        bool init();
 
                 void            deletePlayer();
 
diff --git a/media/libmedia/include/media/DataSourceDesc.h b/media/libmedia/include/media/DataSourceDesc.h
new file mode 100644
index 0000000..c190261
--- /dev/null
+++ b/media/libmedia/include/media/DataSourceDesc.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 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 ANDROID_DATASOURCEDESC_H
+#define ANDROID_DATASOURCEDESC_H
+
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+class DataSource;
+struct MediaHTTPService;
+
+// A binder interface for implementing a stagefright DataSource remotely.
+struct DataSourceDesc : public RefBase {
+public:
+    enum {
+        /* No data source has been set yet */
+        TYPE_NONE     = 0,
+        /* data source is type of MediaDataSource */
+        TYPE_CALLBACK = 1,
+        /* data source is type of FileDescriptor */
+        TYPE_FD       = 2,
+        /* data source is type of Url */
+        TYPE_URL      = 3,
+    };
+
+    DataSourceDesc();
+
+    int mType;
+
+    sp<MediaHTTPService> mHttpService;
+    String8 mUrl;
+    KeyedVector<String8, String8> mHeaders;
+
+    int mFD;
+    int64_t mFDOffset;
+    int64_t mFDLength;
+
+    sp<DataSource> mCallbackSource;
+
+    int64_t mId;
+    int64_t mStartPositionMs;
+    int64_t mEndPositionMs;
+
+private:
+    DISALLOW_EVIL_CONSTRUCTORS(DataSourceDesc);
+};
+
+}; // namespace android
+
+#endif // ANDROID_DATASOURCEDESC_H
diff --git a/media/libmedia/include/media/MediaPlayer2Engine.h b/media/libmedia/include/media/MediaPlayer2Engine.h
index 00f5fb1..29df2d6 100644
--- a/media/libmedia/include/media/MediaPlayer2Engine.h
+++ b/media/libmedia/include/media/MediaPlayer2Engine.h
@@ -36,6 +36,7 @@
 struct AudioPlaybackRate;
 struct BufferingSettings;
 class DataSource;
+struct DataSourceDesc;
 struct IStreamSource;
 struct MediaHTTPService;
 class Parcel;
@@ -47,14 +48,7 @@
 public:
     virtual void            disconnect() = 0;
 
-    virtual status_t        setDataSource(
-            const sp<MediaHTTPService> &httpService,
-            const char *url,
-            const KeyedVector<String8, String8>* headers) = 0;
-
-    virtual status_t        setDataSource(int fd, int64_t offset, int64_t length) = 0;
-    virtual status_t        setDataSource(const sp<IStreamSource>& source) = 0;
-    virtual status_t        setDataSource(const sp<DataSource>& source) = 0;
+    virtual status_t        setDataSource(const sp<DataSourceDesc>& source) = 0;
     virtual status_t        setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww) = 0;
     virtual status_t        getBufferingSettings(
                                     BufferingSettings* buffering /* nonnull */) = 0;
diff --git a/media/libmedia/include/media/MediaPlayer2Interface.h b/media/libmedia/include/media/MediaPlayer2Interface.h
index 699618e..c2cc6e6 100644
--- a/media/libmedia/include/media/MediaPlayer2Interface.h
+++ b/media/libmedia/include/media/MediaPlayer2Interface.h
@@ -41,6 +41,7 @@
 namespace android {
 
 class DataSource;
+struct DataSourceDesc;
 struct MediaHTTPService;
 class Parcel;
 struct ANativeWindowWrapper;
@@ -158,18 +159,7 @@
 
     virtual void        setAudioSink(const sp<AudioSink>& audioSink) { mAudioSink = audioSink; }
 
-    virtual status_t    setDataSource(
-            const sp<MediaHTTPService> &httpService,
-            const char *url,
-            const KeyedVector<String8, String8> *headers = NULL) = 0;
-
-    virtual status_t    setDataSource(int fd, int64_t offset, int64_t length) = 0;
-
-    virtual status_t    setDataSource(const sp<IStreamSource>& /* source */) {
-        return INVALID_OPERATION;
-    }
-
-    virtual status_t    setDataSource(const sp<DataSource>& /* source */) {
+    virtual status_t    setDataSource(const sp<DataSourceDesc>& /* dsd */) {
         return INVALID_OPERATION;
     }
 
diff --git a/media/libmedia/include/media/mediaplayer2.h b/media/libmedia/include/media/mediaplayer2.h
index c96765f..f2fc901 100644
--- a/media/libmedia/include/media/mediaplayer2.h
+++ b/media/libmedia/include/media/mediaplayer2.h
@@ -36,6 +36,7 @@
 struct AVSyncSettings;
 struct ANativeWindowWrapper;
 class DataSource;
+struct DataSourceDesc;
 struct MediaHTTPService;
 
 enum media2_event_type {
@@ -202,13 +203,7 @@
     ~MediaPlayer2();
             void            disconnect();
 
-            status_t        setDataSource(
-                    const sp<MediaHTTPService> &httpService,
-                    const char *url,
-                    const KeyedVector<String8, String8> *headers);
-
-            status_t        setDataSource(int fd, int64_t offset, int64_t length);
-            status_t        setDataSource(const sp<DataSource> &source);
+            status_t        setDataSource(const sp<DataSourceDesc> &dsd);
             status_t        setVideoSurfaceTexture(const sp<ANativeWindowWrapper>& nww);
             status_t        setListener(const sp<MediaPlayer2Listener>& listener);
             status_t        getBufferingSettings(BufferingSettings* buffering /* nonnull */);
diff --git a/media/libmedia/mediaplayer2.cpp b/media/libmedia/mediaplayer2.cpp
index 5c34d4a..ba24da7 100644
--- a/media/libmedia/mediaplayer2.cpp
+++ b/media/libmedia/mediaplayer2.cpp
@@ -34,6 +34,7 @@
 #include <media/AudioSystem.h>
 #include <media/AVSyncSettings.h>
 #include <media/DataSource.h>
+#include <media/DataSourceDesc.h>
 #include <media/MediaAnalyticsItem.h>
 #include <media/NdkWrapper.h>
 
@@ -153,43 +154,16 @@
     return err;
 }
 
-status_t MediaPlayer2::setDataSource(
-        const sp<MediaHTTPService> &httpService,
-        const char *url, const KeyedVector<String8, String8> *headers)
+status_t MediaPlayer2::setDataSource(const sp<DataSourceDesc> &dsd)
 {
-    ALOGV("setDataSource(%s)", url);
-    status_t err = BAD_VALUE;
-    if (url != NULL) {
-        sp<MediaPlayer2Engine> player(MediaPlayer2Manager::get().create(this, mAudioSessionId));
-        if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
-            (NO_ERROR != player->setDataSource(httpService, url, headers))) {
-            player.clear();
-        }
-        err = attachNewPlayer(player);
+    if (dsd == NULL) {
+        return BAD_VALUE;
     }
-    return err;
-}
-
-status_t MediaPlayer2::setDataSource(int fd, int64_t offset, int64_t length)
-{
-    ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length);
+    ALOGV("setDataSource type(%d)", dsd->mType);
     status_t err = UNKNOWN_ERROR;
     sp<MediaPlayer2Engine> player(MediaPlayer2Manager::get().create(this, mAudioSessionId));
     if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
-        (NO_ERROR != player->setDataSource(fd, offset, length))) {
-        player.clear();
-    }
-    err = attachNewPlayer(player);
-    return err;
-}
-
-status_t MediaPlayer2::setDataSource(const sp<DataSource> &source)
-{
-    ALOGV("setDataSource(DataSource)");
-    status_t err = UNKNOWN_ERROR;
-    sp<MediaPlayer2Engine> player(MediaPlayer2Manager::get().create(this, mAudioSessionId));
-    if ((NO_ERROR != doSetRetransmitEndpoint(player)) ||
-        (NO_ERROR != player->setDataSource(source))) {
+        (NO_ERROR != player->setDataSource(dsd))) {
         player.clear();
     }
     err = attachNewPlayer(player);
diff --git a/media/libmedia/nuplayer2/NuPlayer2.cpp b/media/libmedia/nuplayer2/NuPlayer2.cpp
index 2c7f416..35e20e8 100644
--- a/media/libmedia/nuplayer2/NuPlayer2.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2.cpp
@@ -43,6 +43,7 @@
 #include <media/AudioParameter.h>
 #include <media/AudioResamplerPublic.h>
 #include <media/AVSyncSettings.h>
+#include <media/DataSourceDesc.h>
 #include <media/MediaCodecBuffer.h>
 #include <media/NdkWrapper.h>
 
@@ -258,16 +259,6 @@
     mDriver = driver;
 }
 
-void NuPlayer2::setDataSourceAsync(const sp<IStreamSource> &source) {
-    sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
-
-    sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
-
-    msg->setObject("source", new StreamingSource(notify, source));
-    msg->post();
-    mDataSourceType = DATA_SOURCE_TYPE_STREAM;
-}
-
 static bool IsHTTPLiveURL(const char *url) {
     if (!strncasecmp("http://", url, 7)
             || !strncasecmp("https://", url, 8)
@@ -285,93 +276,102 @@
     return false;
 }
 
-void NuPlayer2::setDataSourceAsync(
-        const sp<MediaHTTPService> &httpService,
-        const char *url,
-        const KeyedVector<String8, String8> *headers) {
-
+void NuPlayer2::setDataSourceAsync(const sp<DataSourceDesc> &dsd) {
     sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
-    size_t len = strlen(url);
-
     sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
-
     sp<Source> source;
-    if (IsHTTPLiveURL(url)) {
-        source = new HTTPLiveSource(notify, httpService, url, headers);
-        ALOGV("setDataSourceAsync HTTPLiveSource %s", url);
-        mDataSourceType = DATA_SOURCE_TYPE_HTTP_LIVE;
-    } else if (!strncasecmp(url, "rtsp://", 7)) {
-        source = new RTSPSource(
-                notify, httpService, url, headers, mUIDValid, mUID);
-        ALOGV("setDataSourceAsync RTSPSource %s", url);
-        mDataSourceType = DATA_SOURCE_TYPE_RTSP;
-    } else if ((!strncasecmp(url, "http://", 7)
-                || !strncasecmp(url, "https://", 8))
-                    && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
-                    || strstr(url, ".sdp?"))) {
-        source = new RTSPSource(
-                notify, httpService, url, headers, mUIDValid, mUID, true);
-        ALOGV("setDataSourceAsync RTSPSource http/https/.sdp %s", url);
-        mDataSourceType = DATA_SOURCE_TYPE_RTSP;
-    } else {
-        ALOGV("setDataSourceAsync GenericSource %s", url);
 
-        sp<GenericSource> genericSource =
-                new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+    switch (dsd->mType) {
+        case DataSourceDesc::TYPE_URL:
+        {
+            const char *url = dsd->mUrl.c_str();
+            size_t len = strlen(url);
 
-        status_t err = genericSource->setDataSource(httpService, url, headers);
+            const sp<MediaHTTPService> &httpService = dsd->mHttpService;
+            KeyedVector<String8, String8> *headers = &(dsd->mHeaders);
 
-        if (err == OK) {
-            source = genericSource;
-        } else {
-            ALOGE("Failed to set data source!");
+            if (IsHTTPLiveURL(url)) {
+                source = new HTTPLiveSource(notify, httpService, url, headers);
+                ALOGV("setDataSourceAsync HTTPLiveSource %s", url);
+                mDataSourceType = DATA_SOURCE_TYPE_HTTP_LIVE;
+            } else if (!strncasecmp(url, "rtsp://", 7)) {
+                source = new RTSPSource(
+                        notify, httpService, url, headers, mUIDValid, mUID);
+                ALOGV("setDataSourceAsync RTSPSource %s", url);
+                mDataSourceType = DATA_SOURCE_TYPE_RTSP;
+            } else if ((!strncasecmp(url, "http://", 7)
+                        || !strncasecmp(url, "https://", 8))
+                            && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4]))
+                            || strstr(url, ".sdp?"))) {
+                source = new RTSPSource(
+                        notify, httpService, url, headers, mUIDValid, mUID, true);
+                ALOGV("setDataSourceAsync RTSPSource http/https/.sdp %s", url);
+                mDataSourceType = DATA_SOURCE_TYPE_RTSP;
+            } else {
+                ALOGV("setDataSourceAsync GenericSource %s", url);
+
+                sp<GenericSource> genericSource =
+                        new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+
+                status_t err = genericSource->setDataSource(httpService, url, headers);
+
+                if (err == OK) {
+                    source = genericSource;
+                } else {
+                    ALOGE("Failed to set data source!");
+                }
+
+                // regardless of success/failure
+                mDataSourceType = DATA_SOURCE_TYPE_GENERIC_URL;
+            }
+            break;
         }
 
-        // regardless of success/failure
-        mDataSourceType = DATA_SOURCE_TYPE_GENERIC_URL;
-    }
-    msg->setObject("source", source);
-    msg->post();
-}
+        case DataSourceDesc::TYPE_FD:
+        {
+            sp<GenericSource> genericSource =
+                    new GenericSource(notify, mUIDValid, mUID, mMediaClock);
 
-void NuPlayer2::setDataSourceAsync(int fd, int64_t offset, int64_t length) {
-    sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
+            ALOGV("setDataSourceAsync fd %d/%lld/%lld source: %p",
+                  dsd->mFD, (long long)dsd->mFDOffset, (long long)dsd->mFDLength, source.get());
 
-    sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
+            status_t err = genericSource->setDataSource(dsd->mFD, dsd->mFDOffset, dsd->mFDLength);
 
-    sp<GenericSource> source =
-            new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+            if (err != OK) {
+                ALOGE("Failed to set data source!");
+                source = NULL;
+            } else {
+                source = genericSource;
+            }
 
-    ALOGV("setDataSourceAsync fd %d/%lld/%lld source: %p",
-            fd, (long long)offset, (long long)length, source.get());
+            mDataSourceType = DATA_SOURCE_TYPE_GENERIC_FD;
+            break;
+        }
 
-    status_t err = source->setDataSource(fd, offset, length);
+        case DataSourceDesc::TYPE_CALLBACK:
+        {
+            sp<GenericSource> genericSource =
+                    new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+            status_t err = genericSource->setDataSource(dsd->mCallbackSource);
 
-    if (err != OK) {
-        ALOGE("Failed to set data source!");
-        source = NULL;
+            if (err != OK) {
+                ALOGE("Failed to set data source!");
+                source = NULL;
+            } else {
+                source = genericSource;
+            }
+
+            mDataSourceType = DATA_SOURCE_TYPE_MEDIA;
+            break;
+        }
+
+        default:
+            ALOGE("invalid data source type!");
+            break;
     }
 
     msg->setObject("source", source);
     msg->post();
-    mDataSourceType = DATA_SOURCE_TYPE_GENERIC_FD;
-}
-
-void NuPlayer2::setDataSourceAsync(const sp<DataSource> &dataSource) {
-    sp<AMessage> msg = new AMessage(kWhatSetDataSource, this);
-    sp<AMessage> notify = new AMessage(kWhatSourceNotify, this);
-
-    sp<GenericSource> source = new GenericSource(notify, mUIDValid, mUID, mMediaClock);
-    status_t err = source->setDataSource(dataSource);
-
-    if (err != OK) {
-        ALOGE("Failed to set data source!");
-        source = NULL;
-    }
-
-    msg->setObject("source", source);
-    msg->post();
-    mDataSourceType = DATA_SOURCE_TYPE_MEDIA;
 }
 
 status_t NuPlayer2::getBufferingSettings(
diff --git a/media/libmedia/nuplayer2/NuPlayer2.h b/media/libmedia/nuplayer2/NuPlayer2.h
index 23c4fdf..0764ec3 100644
--- a/media/libmedia/nuplayer2/NuPlayer2.h
+++ b/media/libmedia/nuplayer2/NuPlayer2.h
@@ -30,6 +30,7 @@
 struct ANativeWindowWrapper;
 struct AudioPlaybackRate;
 struct AVSyncSettings;
+struct DataSourceDesc;
 class IDataSource;
 struct MediaClock;
 struct MediaHTTPService;
@@ -43,16 +44,7 @@
 
     void setDriver(const wp<NuPlayer2Driver> &driver);
 
-    void setDataSourceAsync(const sp<IStreamSource> &source);
-
-    void setDataSourceAsync(
-            const sp<MediaHTTPService> &httpService,
-            const char *url,
-            const KeyedVector<String8, String8> *headers);
-
-    void setDataSourceAsync(int fd, int64_t offset, int64_t length);
-
-    void setDataSourceAsync(const sp<DataSource> &source);
+    void setDataSourceAsync(const sp<DataSourceDesc> &dsd);
 
     status_t getBufferingSettings(BufferingSettings* buffering /* nonnull */);
     status_t setBufferingSettings(const BufferingSettings& buffering);
diff --git a/media/libmedia/nuplayer2/NuPlayer2DecoderBase.cpp b/media/libmedia/nuplayer2/NuPlayer2DecoderBase.cpp
index 4d80912..9c1988f 100644
--- a/media/libmedia/nuplayer2/NuPlayer2DecoderBase.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2DecoderBase.cpp
@@ -39,7 +39,9 @@
     // are blocking, but NuPlayer2 needs asynchronous operations.
     mDecoderLooper = new ALooper;
     mDecoderLooper->setName("NPDecoder");
-    mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
+    mDecoderLooper->start(false, /* runOnCallingThread */
+                          true,  /* canCallJava */
+                          ANDROID_PRIORITY_AUDIO);
 }
 
 NuPlayer2::DecoderBase::~DecoderBase() {
diff --git a/media/libmedia/nuplayer2/NuPlayer2Driver.cpp b/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
index e48acea..6137fd1 100644
--- a/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2Driver.cpp
@@ -175,67 +175,7 @@
     return OK;
 }
 
-status_t NuPlayer2Driver::setDataSource(
-        const sp<MediaHTTPService> &httpService,
-        const char *url,
-        const KeyedVector<String8, String8> *headers) {
-    ALOGV("setDataSource(%p) url(%s)", this, uriDebugString(url, false).c_str());
-    Mutex::Autolock autoLock(mLock);
-
-    if (mState != STATE_IDLE) {
-        return INVALID_OPERATION;
-    }
-
-    mState = STATE_SET_DATASOURCE_PENDING;
-
-    mPlayer->setDataSourceAsync(httpService, url, headers);
-
-    while (mState == STATE_SET_DATASOURCE_PENDING) {
-        mCondition.wait(mLock);
-    }
-
-    return mAsyncResult;
-}
-
-status_t NuPlayer2Driver::setDataSource(int fd, int64_t offset, int64_t length) {
-    ALOGV("setDataSource(%p) file(%d)", this, fd);
-    Mutex::Autolock autoLock(mLock);
-
-    if (mState != STATE_IDLE) {
-        return INVALID_OPERATION;
-    }
-
-    mState = STATE_SET_DATASOURCE_PENDING;
-
-    mPlayer->setDataSourceAsync(fd, offset, length);
-
-    while (mState == STATE_SET_DATASOURCE_PENDING) {
-        mCondition.wait(mLock);
-    }
-
-    return mAsyncResult;
-}
-
-status_t NuPlayer2Driver::setDataSource(const sp<IStreamSource> &source) {
-    ALOGV("setDataSource(%p) stream source", this);
-    Mutex::Autolock autoLock(mLock);
-
-    if (mState != STATE_IDLE) {
-        return INVALID_OPERATION;
-    }
-
-    mState = STATE_SET_DATASOURCE_PENDING;
-
-    mPlayer->setDataSourceAsync(source);
-
-    while (mState == STATE_SET_DATASOURCE_PENDING) {
-        mCondition.wait(mLock);
-    }
-
-    return mAsyncResult;
-}
-
-status_t NuPlayer2Driver::setDataSource(const sp<DataSource> &source) {
+status_t NuPlayer2Driver::setDataSource(const sp<DataSourceDesc> &dsd) {
     ALOGV("setDataSource(%p) callback source", this);
     Mutex::Autolock autoLock(mLock);
 
@@ -245,7 +185,7 @@
 
     mState = STATE_SET_DATASOURCE_PENDING;
 
-    mPlayer->setDataSourceAsync(source);
+    mPlayer->setDataSourceAsync(dsd);
 
     while (mState == STATE_SET_DATASOURCE_PENDING) {
         mCondition.wait(mLock);
diff --git a/media/libmedia/nuplayer2/NuPlayer2Driver.h b/media/libmedia/nuplayer2/NuPlayer2Driver.h
index 7bbb367..55fc9ef 100644
--- a/media/libmedia/nuplayer2/NuPlayer2Driver.h
+++ b/media/libmedia/nuplayer2/NuPlayer2Driver.h
@@ -32,16 +32,7 @@
 
     virtual status_t setUID(uid_t uid);
 
-    virtual status_t setDataSource(
-            const sp<MediaHTTPService> &httpService,
-            const char *url,
-            const KeyedVector<String8, String8> *headers);
-
-    virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
-
-    virtual status_t setDataSource(const sp<IStreamSource> &source);
-
-    virtual status_t setDataSource(const sp<DataSource>& dataSource);
+    virtual status_t setDataSource(const sp<DataSourceDesc> &dsd) override;
 
     virtual status_t setVideoSurfaceTexture(const sp<ANativeWindowWrapper> &nww);