Merge "Codec2: C2Block2D rework"
diff --git a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
index 9506cd1..bf97db9 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
+++ b/drm/mediadrm/plugins/clearkey/hidl/DrmPlugin.cpp
@@ -45,10 +45,12 @@
 namespace clearkey {
 
 DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
-        : mSessionLibrary(sessionLibrary) {
+        : mSessionLibrary(sessionLibrary),
+          mOpenSessionOkCount(0),
+          mCloseSessionOkCount(0),
+          mCloseSessionNotOpenedCount(0) {
     mPlayPolicy.clear();
     initProperties();
-
 }
 
 void DrmPlugin::initProperties() {
@@ -77,6 +79,7 @@
 
     setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO);
     _hidl_cb(Status::OK, toHidlVec(sessionId));
+    mOpenSessionOkCount++;
     return Void();
 }
 
@@ -87,9 +90,11 @@
 
     sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
     if (session.get()) {
+        mCloseSessionOkCount++;
         mSessionLibrary->destroySession(session);
         return Status::OK;
     }
+    mCloseSessionNotOpenedCount++;
     return Status::ERROR_DRM_SESSION_NOT_OPENED;
 }
 
@@ -364,6 +369,50 @@
     return Status::OK;
 }
 
+Return<void> DrmPlugin::getMetrics(getMetrics_cb _hidl_cb) {
+    // Set the open session count metric.
+    DrmMetricGroup::Attribute openSessionOkAttribute = {
+      "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
+    };
+    DrmMetricGroup::Value openSessionMetricValue = {
+      "count", DrmMetricGroup::ValueType::INT64_TYPE, mOpenSessionOkCount, 0.0, ""
+    };
+    DrmMetricGroup::Metric openSessionMetric = {
+      "open_session", { openSessionOkAttribute }, { openSessionMetricValue }
+    };
+
+    // Set the close session count metric.
+    DrmMetricGroup::Attribute closeSessionOkAttribute = {
+      "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
+    };
+    DrmMetricGroup::Value closeSessionMetricValue = {
+      "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionOkCount, 0.0, ""
+    };
+    DrmMetricGroup::Metric closeSessionMetric = {
+      "close_session", { closeSessionOkAttribute }, { closeSessionMetricValue }
+    };
+
+    // Set the close session, not opened metric.
+    DrmMetricGroup::Attribute closeSessionNotOpenedAttribute = {
+      "status", DrmMetricGroup::ValueType::INT64_TYPE,
+      (int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, 0.0, ""
+    };
+    DrmMetricGroup::Value closeSessionNotOpenedMetricValue = {
+      "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionNotOpenedCount, 0.0, ""
+    };
+    DrmMetricGroup::Metric closeSessionNotOpenedMetric = {
+      "close_session", { closeSessionNotOpenedAttribute }, { closeSessionNotOpenedMetricValue }
+    };
+
+    DrmMetricGroup metrics = { { openSessionMetric, closeSessionMetric,
+                                closeSessionNotOpenedMetric } };
+
+    _hidl_cb(Status::OK, hidl_vec<DrmMetricGroup>({metrics}));
+    return Void();
+}
+
+
+
 }  // namespace clearkey
 }  // namespace V1_1
 }  // namespace drm
diff --git a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
index 5ae9833..64c8262 100644
--- a/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/hidl/include/DrmPlugin.h
@@ -38,6 +38,7 @@
 using ::android::hardware::drm::V1_0::SecureStop;
 using ::android::hardware::drm::V1_0::SecureStopId;
 using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::drm::V1_1::DrmMetricGroup;
 
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
@@ -45,6 +46,7 @@
 using ::android::hardware::Void;
 using ::android::sp;
 
+
 struct DrmPlugin : public IDrmPlugin {
     explicit DrmPlugin(SessionLibrary* sessionLibrary);
 
@@ -163,6 +165,8 @@
     Return<Status> setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
             SecurityLevel level) override;
 
+    Return<void> getMetrics(getMetrics_cb _hidl_cb) override;
+
     Return<void> getPropertyString(
         const hidl_string& name,
         getPropertyString_cb _hidl_cb) override;
@@ -302,11 +306,6 @@
         return Void();
     }
 
-    Return<void> getMetrics(getMetrics_cb _hidl_cb) {
-        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<DrmMetricGroup>());
-        return Void();
-    }
-
     Return<void> getSecureStopIds(getSecureStopIds_cb _hidl_cb) {
         _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<SecureStopId>());
         return Void();
@@ -340,6 +339,9 @@
     std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel;
     sp<IDrmPluginListener> mListener;
     SessionLibrary *mSessionLibrary;
+    int64_t mOpenSessionOkCount;
+    int64_t mCloseSessionOkCount;
+    int64_t mCloseSessionNotOpenedCount;
 
     CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin);
 };
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index 6d0b1cc..a8a366b 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -165,9 +165,9 @@
                     || !strcasecmp(MEDIA_MIMETYPE_AUDIO_SCRAMBLED, mime));
 }
 
-status_t MPEG2TSExtractor::setMediaCas(const HInterfaceToken &casToken) {
+status_t MPEG2TSExtractor::setMediaCas(const uint8_t* casToken, size_t size) {
     HalToken halToken;
-    halToken.setToExternal((uint8_t*)casToken.data(), casToken.size());
+    halToken.setToExternal((uint8_t*)casToken, size);
     sp<ICas> cas = ICas::castFrom(retrieveHalInterface(halToken));
     ALOGD("setMediaCas: %p", cas.get());
 
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.h b/media/extractors/mpeg2/MPEG2TSExtractor.h
index 57cb675..fc15501 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.h
@@ -45,7 +45,7 @@
 
     virtual sp<MetaData> getMetaData();
 
-    virtual status_t setMediaCas(const HInterfaceToken &casToken) override;
+    virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) override;
 
     virtual uint32_t flags() const;
     virtual const char * name() { return "MPEG2TSExtractor"; }
diff --git a/media/libmedia/MediaPlayer2Manager.cpp b/media/libmedia/MediaPlayer2Manager.cpp
index 76b4c0b..4c0a7ac 100644
--- a/media/libmedia/MediaPlayer2Manager.cpp
+++ b/media/libmedia/MediaPlayer2Manager.cpp
@@ -82,7 +82,6 @@
 using android::BAD_VALUE;
 using android::NOT_ENOUGH_DATA;
 using android::Parcel;
-using android::media::VolumeShaper;
 
 // Max number of entries in the filter.
 const int kMaxFilterSize = 64;  // I pulled that out of thin air.
@@ -503,7 +502,6 @@
     mStatus = NO_INIT;
     mAudioSessionId = audioSessionId;
     mUid = uid;
-    mRetransmitEndpointValid = false;
     mAudioAttributes = NULL;
 
 #if CALLBACK_ANTAGONIZER
@@ -605,14 +603,6 @@
         return status;
     }
 
-    // Set the re-transmission endpoint if one was chosen.
-    if (mRetransmitEndpointValid) {
-        status = p->setRetransmitEndpoint(&mRetransmitEndpoint);
-        if (status != NO_ERROR) {
-            ALOGE("setRetransmitEndpoint error: %d", status);
-        }
-    }
-
     return status;
 }
 
@@ -927,34 +917,6 @@
     return OK;
 }
 
-VolumeShaper::Status MediaPlayer2Manager::Client::applyVolumeShaper(
-        const sp<VolumeShaper::Configuration>& configuration,
-        const sp<VolumeShaper::Operation>& operation) {
-    // for hardware output, call player instead
-    ALOGV("Client::applyVolumeShaper(%p)", this);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    {
-        Mutex::Autolock l(mLock);
-        if (mAudioOutput.get() != nullptr) {
-            return mAudioOutput->applyVolumeShaper(configuration, operation);
-        }
-    }
-    return VolumeShaper::Status(INVALID_OPERATION);
-}
-
-sp<VolumeShaper::State> MediaPlayer2Manager::Client::getVolumeShaperState(int id) {
-    // for hardware output, call player instead
-    ALOGV("Client::getVolumeShaperState(%p)", this);
-    sp<MediaPlayer2Interface> p = getPlayer();
-    {
-        Mutex::Autolock l(mLock);
-        if (mAudioOutput.get() != nullptr) {
-            return mAudioOutput->getVolumeShaperState(id);
-        }
-    }
-    return nullptr;
-}
-
 status_t MediaPlayer2Manager::Client::seekTo(int msec, MediaPlayer2SeekMode mode)
 {
     ALOGV("[%d] seekTo(%d, %d)", mConnId, msec, mode);
@@ -966,7 +928,6 @@
 status_t MediaPlayer2Manager::Client::reset()
 {
     ALOGV("[%d] reset", mConnId);
-    mRetransmitEndpointValid = false;
     sp<MediaPlayer2Interface> p = getPlayer();
     if (p == 0) return UNKNOWN_ERROR;
     return p->reset();
@@ -1069,53 +1030,6 @@
     return p->getParameter(key, reply);
 }
 
-status_t MediaPlayer2Manager::Client::setRetransmitEndpoint(
-        const struct sockaddr_in* endpoint) {
-
-    if (NULL != endpoint) {
-        uint32_t a = ntohl(endpoint->sin_addr.s_addr);
-        uint16_t p = ntohs(endpoint->sin_port);
-        ALOGV("[%d] setRetransmitEndpoint(%u.%u.%u.%u:%hu)", mConnId,
-                (a >> 24), (a >> 16) & 0xFF, (a >> 8) & 0xFF, (a & 0xFF), p);
-    } else {
-        ALOGV("[%d] setRetransmitEndpoint = <none>", mConnId);
-    }
-
-    // Right now, the only valid time to set a retransmit endpoint is before
-    // setDataSource.
-
-    if (NULL != endpoint) {
-        Mutex::Autolock lock(mLock);
-        mRetransmitEndpoint = *endpoint;
-        mRetransmitEndpointValid = true;
-    } else {
-        Mutex::Autolock lock(mLock);
-        mRetransmitEndpointValid = false;
-    }
-
-    return NO_ERROR;
-}
-
-status_t MediaPlayer2Manager::Client::getRetransmitEndpoint(
-        struct sockaddr_in* endpoint)
-{
-    if (NULL == endpoint)
-        return BAD_VALUE;
-
-    sp<MediaPlayer2Interface> p = getPlayer();
-
-    if (p != NULL)
-        return p->getRetransmitEndpoint(endpoint);
-
-    Mutex::Autolock lock(mLock);
-    if (!mRetransmitEndpointValid)
-        return NO_INIT;
-
-    *endpoint = mRetransmitEndpoint;
-
-    return NO_ERROR;
-}
-
 void MediaPlayer2Manager::Client::notify(
         const wp<MediaPlayer2Engine> &listener, int msg, int ext1, int ext2, const Parcel *obj)
 {
@@ -1319,7 +1233,6 @@
       mSendLevel(0.0),
       mAuxEffectId(0),
       mFlags(AUDIO_OUTPUT_FLAG_NONE),
-      mVolumeHandler(new media::VolumeHandler()),
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
       mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
       mDeviceCallbackEnabled(false),
@@ -1790,24 +1703,6 @@
     ALOGV("setVolume");
     t->setVolume(mLeftVolume, mRightVolume);
 
-    // Restore VolumeShapers for the MediaPlayer2 in case the track was recreated
-    // due to an output sink error (e.g. offload to non-offload switch).
-    mVolumeHandler->forall([&t](const VolumeShaper &shaper) -> VolumeShaper::Status {
-        sp<VolumeShaper::Operation> operationToEnd =
-                new VolumeShaper::Operation(shaper.mOperation);
-        // TODO: Ideally we would restore to the exact xOffset position
-        // as returned by getVolumeShaperState(), but we don't have that
-        // information when restoring at the client unless we periodically poll
-        // the server or create shared memory state.
-        //
-        // For now, we simply advance to the end of the VolumeShaper effect
-        // if it has been started.
-        if (shaper.isStarted()) {
-            operationToEnd->setNormalizedTime(1.f);
-        }
-        return t->applyVolumeShaper(shaper.mConfiguration, operationToEnd);
-    });
-
     mSampleRateHz = sampleRate;
     mFlags = flags;
     mMsecsPerFrame = 1E3f / (mPlaybackRate.mSpeed * sampleRate);
@@ -1852,9 +1747,6 @@
         mTrack->setVolume(mLeftVolume, mRightVolume);
         mTrack->setAuxEffectSendLevel(mSendLevel);
         status_t status = mTrack->start();
-        if (status == NO_ERROR) {
-            mVolumeHandler->setStarted();
-        }
         return status;
     }
     return NO_INIT;
@@ -2091,67 +1983,6 @@
     return NO_ERROR;
 }
 
-VolumeShaper::Status MediaPlayer2Manager::AudioOutput::applyVolumeShaper(
-                const sp<VolumeShaper::Configuration>& configuration,
-                const sp<VolumeShaper::Operation>& operation)
-{
-    Mutex::Autolock lock(mLock);
-    ALOGV("AudioOutput::applyVolumeShaper");
-
-    mVolumeHandler->setIdIfNecessary(configuration);
-
-    VolumeShaper::Status status;
-    if (mTrack != 0) {
-        status = mTrack->applyVolumeShaper(configuration, operation);
-        if (status >= 0) {
-            (void)mVolumeHandler->applyVolumeShaper(configuration, operation);
-            if (mTrack->isPlaying()) { // match local AudioTrack to properly restore.
-                mVolumeHandler->setStarted();
-            }
-        }
-    } else {
-        // VolumeShapers are not affected when a track moves between players for
-        // gapless playback (setNextMediaPlayer).
-        // We forward VolumeShaper operations that do not change configuration
-        // to the new player so that unducking may occur as expected.
-        // Unducking is an idempotent operation, same if applied back-to-back.
-        if (configuration->getType() == VolumeShaper::Configuration::TYPE_ID
-                && mNextOutput != nullptr) {
-            ALOGV("applyVolumeShaper: Attempting to forward missed operation: %s %s",
-                    configuration->toString().c_str(), operation->toString().c_str());
-            Mutex::Autolock nextLock(mNextOutput->mLock);
-
-            // recycled track should be forwarded from this AudioSink by switchToNextOutput
-            sp<AudioTrack> track = mNextOutput->mRecycledTrack;
-            if (track != nullptr) {
-                ALOGD("Forward VolumeShaper operation to recycled track %p", track.get());
-                (void)track->applyVolumeShaper(configuration, operation);
-            } else {
-                // There is a small chance that the unduck occurs after the next
-                // player has already started, but before it is registered to receive
-                // the unduck command.
-                track = mNextOutput->mTrack;
-                if (track != nullptr) {
-                    ALOGD("Forward VolumeShaper operation to track %p", track.get());
-                    (void)track->applyVolumeShaper(configuration, operation);
-                }
-            }
-        }
-        status = mVolumeHandler->applyVolumeShaper(configuration, operation);
-    }
-    return status;
-}
-
-sp<VolumeShaper::State> MediaPlayer2Manager::AudioOutput::getVolumeShaperState(int id)
-{
-    Mutex::Autolock lock(mLock);
-    if (mTrack != 0) {
-        return mTrack->getVolumeShaperState(id);
-    } else {
-        return mVolumeHandler->getVolumeShaperState(id);
-    }
-}
-
 // static
 void MediaPlayer2Manager::AudioOutput::CallbackWrapper(
         int event, void *cookie, void *info) {
diff --git a/media/libmedia/MediaPlayer2Manager.h b/media/libmedia/MediaPlayer2Manager.h
index cdbbc70..95b875b 100644
--- a/media/libmedia/MediaPlayer2Manager.h
+++ b/media/libmedia/MediaPlayer2Manager.h
@@ -132,11 +132,6 @@
         virtual status_t        setParameters(const String8& keyValuePairs);
         virtual String8         getParameters(const String8& keys);
 
-        virtual media::VolumeShaper::Status applyVolumeShaper(
-                                        const sp<media::VolumeShaper::Configuration>& configuration,
-                                        const sp<media::VolumeShaper::Operation>& operation) override;
-        virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) override;
-
         // AudioRouting
         virtual status_t        setOutputDevice(audio_port_handle_t deviceId);
         virtual status_t        getRoutedDeviceId(audio_port_handle_t* deviceId);
@@ -170,7 +165,6 @@
         float                   mSendLevel;
         int                     mAuxEffectId;
         audio_output_flags_t    mFlags;
-        sp<media::VolumeHandler>       mVolumeHandler;
         audio_port_handle_t     mSelectedDeviceId;
         audio_port_handle_t     mRoutedDeviceId;
         bool                    mDeviceCallbackEnabled;
@@ -278,15 +272,8 @@
         virtual status_t        attachAuxEffect(int effectId);
         virtual status_t        setParameter(int key, const Parcel &request);
         virtual status_t        getParameter(int key, Parcel *reply);
-        virtual status_t        setRetransmitEndpoint(const struct sockaddr_in* endpoint);
-        virtual status_t        getRetransmitEndpoint(struct sockaddr_in* endpoint);
         virtual status_t        setNextPlayer(const sp<MediaPlayer2Engine>& player);
 
-        virtual media::VolumeShaper::Status applyVolumeShaper(
-                                        const sp<media::VolumeShaper::Configuration>& configuration,
-                                        const sp<media::VolumeShaper::Operation>& operation) override;
-        virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) override;
-
         virtual status_t        setDataSource(const sp<DataSourceDesc> &dsd);
 
         static  void            notify(const wp<MediaPlayer2Engine> &listener, int msg,
@@ -363,8 +350,6 @@
                     audio_attributes_t *         mAudioAttributes;
                     uid_t                        mUid;
                     sp<ANativeWindowWrapper>     mConnectedWindow;
-                    struct sockaddr_in           mRetransmitEndpoint;
-                    bool                         mRetransmitEndpointValid;
                     sp<Client>                   mNextClient;
 
         // Metadata filters.
diff --git a/media/libmedia/include/media/MediaPlayer2Engine.h b/media/libmedia/include/media/MediaPlayer2Engine.h
index 29df2d6..2d1a24b 100644
--- a/media/libmedia/include/media/MediaPlayer2Engine.h
+++ b/media/libmedia/include/media/MediaPlayer2Engine.h
@@ -23,7 +23,6 @@
 #include <system/audio.h>
 
 #include <media/MediaSource.h>
-#include <media/VolumeShaper.h>
 
 // Fwd decl to make sure everyone agrees that the scope of struct sockaddr_in is
 // global, and not in android::
@@ -77,15 +76,8 @@
     virtual status_t        attachAuxEffect(int effectId) = 0;
     virtual status_t        setParameter(int key, const Parcel& request) = 0;
     virtual status_t        getParameter(int key, Parcel* reply) = 0;
-    virtual status_t        setRetransmitEndpoint(const struct sockaddr_in* endpoint) = 0;
-    virtual status_t        getRetransmitEndpoint(struct sockaddr_in* endpoint) = 0;
     virtual status_t        setNextPlayer(const sp<MediaPlayer2Engine>& next) = 0;
 
-    virtual media::VolumeShaper::Status applyVolumeShaper(
-                                    const sp<media::VolumeShaper::Configuration>& configuration,
-                                    const sp<media::VolumeShaper::Operation>& operation) = 0;
-    virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) = 0;
-
     // Modular DRM
     virtual status_t        prepareDrm(const uint8_t uuid[16],
                                     const Vector<uint8_t>& drmSessionId) = 0;
diff --git a/media/libmedia/include/media/MediaPlayer2Interface.h b/media/libmedia/include/media/MediaPlayer2Interface.h
index c2cc6e6..be300bb 100644
--- a/media/libmedia/include/media/MediaPlayer2Interface.h
+++ b/media/libmedia/include/media/MediaPlayer2Interface.h
@@ -138,11 +138,6 @@
         virtual status_t    setParameters(const String8& /* keyValuePairs */) { return NO_ERROR; }
         virtual String8     getParameters(const String8& /* keys */) { return String8::empty(); }
 
-        virtual media::VolumeShaper::Status applyVolumeShaper(
-                                    const sp<media::VolumeShaper::Configuration>& configuration,
-                                    const sp<media::VolumeShaper::Operation>& operation);
-        virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id);
-
         // AudioRouting
         virtual status_t    setOutputDevice(audio_port_handle_t deviceId);
         virtual status_t    getRoutedDeviceId(audio_port_handle_t* deviceId);
@@ -218,13 +213,6 @@
     virtual status_t    setParameter(int key, const Parcel &request) = 0;
     virtual status_t    getParameter(int key, Parcel *reply) = 0;
 
-    // default no-op implementation of optional extensions
-    virtual status_t setRetransmitEndpoint(const struct sockaddr_in* /* endpoint */) {
-        return INVALID_OPERATION;
-    }
-    virtual status_t getRetransmitEndpoint(struct sockaddr_in* /* endpoint */) {
-        return INVALID_OPERATION;
-    }
     virtual status_t setNextPlayer(const sp<MediaPlayer2Interface>& /* next */) {
         return OK;
     }
diff --git a/media/libmedia/include/media/mediaplayer2.h b/media/libmedia/include/media/mediaplayer2.h
index f2fc901..c8b124c 100644
--- a/media/libmedia/include/media/mediaplayer2.h
+++ b/media/libmedia/include/media/mediaplayer2.h
@@ -244,13 +244,8 @@
             status_t        attachAuxEffect(int effectId);
             status_t        setParameter(int key, const Parcel& request);
             status_t        getParameter(int key, Parcel* reply);
-            status_t        setRetransmitEndpoint(const char* addrString, uint16_t port);
             status_t        setNextMediaPlayer(const sp<MediaPlayer2>& player);
 
-            media::VolumeShaper::Status applyVolumeShaper(
-                                    const sp<media::VolumeShaper::Configuration>& configuration,
-                                    const sp<media::VolumeShaper::Operation>& operation);
-            sp<media::VolumeShaper::State> getVolumeShaperState(int id);
             // Modular DRM
             status_t        prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId);
             status_t        releaseDrm();
@@ -266,7 +261,6 @@
             status_t        getDuration_l(int *msec);
             status_t        attachNewPlayer(const sp<MediaPlayer2Engine>& player);
             status_t        reset_l();
-            status_t        doSetRetransmitEndpoint(const sp<MediaPlayer2Engine>& player);
             status_t        checkStateForKeySet_l(int key);
 
     sp<MediaPlayer2Engine>      mPlayer;
@@ -292,8 +286,6 @@
     int                         mVideoHeight;
     audio_session_t             mAudioSessionId;
     float                       mSendLevel;
-    struct sockaddr_in          mRetransmitEndpoint;
-    bool                        mRetransmitEndpointValid;
 };
 
 }; // namespace android
diff --git a/media/libmedia/mediaplayer2.cpp b/media/libmedia/mediaplayer2.cpp
index ba24da7..1eb3795 100644
--- a/media/libmedia/mediaplayer2.cpp
+++ b/media/libmedia/mediaplayer2.cpp
@@ -50,8 +50,6 @@
 
 namespace android {
 
-using media::VolumeShaper;
-
 MediaPlayer2::MediaPlayer2()
 {
     ALOGV("constructor");
@@ -73,7 +71,6 @@
     mAudioSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
     AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
     mSendLevel = 0;
-    mRetransmitEndpointValid = false;
 }
 
 MediaPlayer2::~MediaPlayer2()
@@ -111,7 +108,6 @@
     mSeekPosition = -1;
     mSeekMode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC;
     mVideoWidth = mVideoHeight = 0;
-    mRetransmitEndpointValid = false;
 }
 
 status_t MediaPlayer2::setListener(const sp<MediaPlayer2Listener>& listener)
@@ -162,8 +158,7 @@
     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(dsd))) {
+    if (NO_ERROR != player->setDataSource(dsd)) {
         player.clear();
     }
     err = attachNewPlayer(player);
@@ -589,20 +584,6 @@
     return NO_ERROR;
 }
 
-status_t MediaPlayer2::doSetRetransmitEndpoint(const sp<MediaPlayer2Engine>& player) {
-    Mutex::Autolock _l(mLock);
-
-    if (player == NULL) {
-        return UNKNOWN_ERROR;
-    }
-
-    if (mRetransmitEndpointValid) {
-        return player->setRetransmitEndpoint(&mRetransmitEndpoint);
-    }
-
-    return OK;
-}
-
 status_t MediaPlayer2::reset()
 {
     ALOGV("reset");
@@ -782,34 +763,6 @@
     return INVALID_OPERATION;
 }
 
-status_t MediaPlayer2::setRetransmitEndpoint(const char* addrString,
-                                            uint16_t port) {
-    ALOGV("MediaPlayer2::setRetransmitEndpoint(%s:%hu)",
-            addrString ? addrString : "(null)", port);
-
-    Mutex::Autolock _l(mLock);
-    if ((mPlayer != NULL) || (mCurrentState != MEDIA_PLAYER2_IDLE))
-        return INVALID_OPERATION;
-
-    if (NULL == addrString) {
-        mRetransmitEndpointValid = false;
-        return OK;
-    }
-
-    struct in_addr saddr;
-    if(!inet_aton(addrString, &saddr)) {
-        return BAD_VALUE;
-    }
-
-    memset(&mRetransmitEndpoint, 0, sizeof(mRetransmitEndpoint));
-    mRetransmitEndpoint.sin_family = AF_INET;
-    mRetransmitEndpoint.sin_addr   = saddr;
-    mRetransmitEndpoint.sin_port   = htons(port);
-    mRetransmitEndpointValid       = true;
-
-    return OK;
-}
-
 void MediaPlayer2::notify(int msg, int ext1, int ext2, const Parcel *obj)
 {
     ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2);
@@ -949,27 +902,6 @@
     return mPlayer->setNextPlayer(next == NULL ? NULL : next->mPlayer);
 }
 
-VolumeShaper::Status MediaPlayer2::applyVolumeShaper(
-        const sp<VolumeShaper::Configuration>& configuration,
-        const sp<VolumeShaper::Operation>& operation)
-{
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == nullptr) {
-        return VolumeShaper::Status(NO_INIT);
-    }
-    VolumeShaper::Status status = mPlayer->applyVolumeShaper(configuration, operation);
-    return status;
-}
-
-sp<VolumeShaper::State> MediaPlayer2::getVolumeShaperState(int id)
-{
-    Mutex::Autolock _l(mLock);
-    if (mPlayer == nullptr) {
-        return nullptr;
-    }
-    return mPlayer->getVolumeShaperState(id);
-}
-
 // Modular DRM
 status_t MediaPlayer2::prepareDrm(const uint8_t uuid[16], const Vector<uint8_t>& drmSessionId)
 {
diff --git a/media/libmedia/nuplayer2/Android.bp b/media/libmedia/nuplayer2/Android.bp
index 700c840..1f4455f 100644
--- a/media/libmedia/nuplayer2/Android.bp
+++ b/media/libmedia/nuplayer2/Android.bp
@@ -2,8 +2,8 @@
 
     srcs: [
         "JWakeLock.cpp",
-        "GenericSource.cpp",
-        "HTTPLiveSource.cpp",
+        "GenericSource2.cpp",
+        "HTTPLiveSource2.cpp",
         "NuPlayer2.cpp",
         "NuPlayer2CCDecoder.cpp",
         "NuPlayer2Decoder.cpp",
@@ -12,9 +12,7 @@
         "NuPlayer2Driver.cpp",
         "NuPlayer2Drm.cpp",
         "NuPlayer2Renderer.cpp",
-        "NuPlayer2StreamListener.cpp",
-        "RTSPSource.cpp",
-        "StreamingSource.cpp",
+        "RTSPSource2.cpp",
     ],
 
     header_libs: [
diff --git a/media/libmedia/nuplayer2/GenericSource.cpp b/media/libmedia/nuplayer2/GenericSource2.cpp
similarity index 93%
rename from media/libmedia/nuplayer2/GenericSource.cpp
rename to media/libmedia/nuplayer2/GenericSource2.cpp
index 6907216..0351a76 100644
--- a/media/libmedia/nuplayer2/GenericSource.cpp
+++ b/media/libmedia/nuplayer2/GenericSource2.cpp
@@ -15,9 +15,9 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "GenericSource"
+#define LOG_TAG "GenericSource2"
 
-#include "GenericSource.h"
+#include "GenericSource2.h"
 #include "NuPlayer2Drm.h"
 
 #include "AnotherPacketSource.h"
@@ -52,7 +52,7 @@
 //static const int kPausePlaybackMarkMs  = 2000;  // 2secs
 static const int kResumePlaybackMarkMs = 15000;  // 15secs
 
-NuPlayer2::GenericSource::GenericSource(
+NuPlayer2::GenericSource2::GenericSource2(
         const sp<AMessage> &notify,
         bool uidValid,
         uid_t uid,
@@ -79,7 +79,7 @@
       mFd(-1),
       mBitrate(-1ll),
       mPendingReadBufferTypes(0) {
-    ALOGV("GenericSource");
+    ALOGV("GenericSource2");
     CHECK(mediaClock != NULL);
 
     mBufferingSettings.mInitialMarkMs = kInitialMarkMs;
@@ -87,7 +87,7 @@
     resetDataSource();
 }
 
-void NuPlayer2::GenericSource::resetDataSource() {
+void NuPlayer2::GenericSource2::resetDataSource() {
     ALOGV("resetDataSource");
 
     mHTTPService.clear();
@@ -110,7 +110,7 @@
     mMimes.clear();
 }
 
-status_t NuPlayer2::GenericSource::setDataSource(
+status_t NuPlayer2::GenericSource2::setDataSource(
         const sp<MediaHTTPService> &httpService,
         const char *url,
         const KeyedVector<String8, String8> *headers) {
@@ -131,7 +131,7 @@
     return OK;
 }
 
-status_t NuPlayer2::GenericSource::setDataSource(
+status_t NuPlayer2::GenericSource2::setDataSource(
         int fd, int64_t offset, int64_t length) {
     Mutex::Autolock _l(mLock);
     ALOGV("setDataSource %d/%lld/%lld", fd, (long long)offset, (long long)length);
@@ -147,7 +147,7 @@
     return OK;
 }
 
-status_t NuPlayer2::GenericSource::setDataSource(const sp<DataSource>& source) {
+status_t NuPlayer2::GenericSource2::setDataSource(const sp<DataSource>& source) {
     Mutex::Autolock _l(mLock);
     ALOGV("setDataSource (source: %p)", source.get());
 
@@ -156,12 +156,12 @@
     return OK;
 }
 
-sp<MetaData> NuPlayer2::GenericSource::getFileFormatMeta() const {
+sp<MetaData> NuPlayer2::GenericSource2::getFileFormatMeta() const {
     Mutex::Autolock _l(mLock);
     return mFileMeta;
 }
 
-status_t NuPlayer2::GenericSource::initFromDataSource() {
+status_t NuPlayer2::GenericSource2::initFromDataSource() {
     sp<IMediaExtractor> extractor;
     CHECK(mDataSource != NULL || mFd != -1);
     sp<DataSource> dataSource = mDataSource;
@@ -294,7 +294,7 @@
     return OK;
 }
 
-status_t NuPlayer2::GenericSource::getBufferingSettings(
+status_t NuPlayer2::GenericSource2::getBufferingSettings(
         BufferingSettings* buffering /* nonnull */) {
     {
         Mutex::Autolock _l(mLock);
@@ -305,7 +305,7 @@
     return OK;
 }
 
-status_t NuPlayer2::GenericSource::setBufferingSettings(const BufferingSettings& buffering) {
+status_t NuPlayer2::GenericSource2::setBufferingSettings(const BufferingSettings& buffering) {
     ALOGV("setBufferingSettings{%s}", buffering.toString().string());
 
     Mutex::Autolock _l(mLock);
@@ -313,7 +313,7 @@
     return OK;
 }
 
-status_t NuPlayer2::GenericSource::startSources() {
+status_t NuPlayer2::GenericSource2::startSources() {
     // Start the selected A/V tracks now before we start buffering.
     // Widevine sources might re-initialize crypto when starting, if we delay
     // this to start(), all data buffered during prepare would be wasted.
@@ -334,7 +334,7 @@
     return OK;
 }
 
-int64_t NuPlayer2::GenericSource::getLastReadPosition() {
+int64_t NuPlayer2::GenericSource2::getLastReadPosition() {
     if (mAudioTrack.mSource != NULL) {
         return mAudioTimeUs;
     } else if (mVideoTrack.mSource != NULL) {
@@ -344,13 +344,13 @@
     }
 }
 
-bool NuPlayer2::GenericSource::isStreaming() const {
+bool NuPlayer2::GenericSource2::isStreaming() const {
     Mutex::Autolock _l(mLock);
     return mIsStreaming;
 }
 
-NuPlayer2::GenericSource::~GenericSource() {
-    ALOGV("~GenericSource");
+NuPlayer2::GenericSource2::~GenericSource2() {
+    ALOGV("~GenericSource2");
     if (mLooper != NULL) {
         mLooper->unregisterHandler(id());
         mLooper->stop();
@@ -361,7 +361,7 @@
     resetDataSource();
 }
 
-void NuPlayer2::GenericSource::prepareAsync() {
+void NuPlayer2::GenericSource2::prepareAsync() {
     Mutex::Autolock _l(mLock);
     ALOGV("prepareAsync: (looper: %d)", (mLooper != NULL));
 
@@ -379,7 +379,7 @@
     msg->post();
 }
 
-void NuPlayer2::GenericSource::onPrepareAsync() {
+void NuPlayer2::GenericSource2::onPrepareAsync() {
     ALOGV("onPrepareAsync: mDataSource: %d", (mDataSource != NULL));
 
     // delayed data source creation
@@ -460,7 +460,7 @@
     ALOGV("onPrepareAsync: Done");
 }
 
-void NuPlayer2::GenericSource::finishPrepareAsync() {
+void NuPlayer2::GenericSource2::finishPrepareAsync() {
     ALOGV("finishPrepareAsync");
 
     status_t err = startSources();
@@ -487,7 +487,7 @@
     }
 }
 
-void NuPlayer2::GenericSource::notifyPreparedAndCleanup(status_t err) {
+void NuPlayer2::GenericSource2::notifyPreparedAndCleanup(status_t err) {
     if (err != OK) {
         mDataSource.clear();
         mCachedSource.clear();
@@ -500,7 +500,7 @@
     notifyPrepared(err);
 }
 
-void NuPlayer2::GenericSource::start() {
+void NuPlayer2::GenericSource2::start() {
     Mutex::Autolock _l(mLock);
     ALOGI("start");
 
@@ -515,22 +515,22 @@
     mStarted = true;
 }
 
-void NuPlayer2::GenericSource::stop() {
+void NuPlayer2::GenericSource2::stop() {
     Mutex::Autolock _l(mLock);
     mStarted = false;
 }
 
-void NuPlayer2::GenericSource::pause() {
+void NuPlayer2::GenericSource2::pause() {
     Mutex::Autolock _l(mLock);
     mStarted = false;
 }
 
-void NuPlayer2::GenericSource::resume() {
+void NuPlayer2::GenericSource2::resume() {
     Mutex::Autolock _l(mLock);
     mStarted = true;
 }
 
-void NuPlayer2::GenericSource::disconnect() {
+void NuPlayer2::GenericSource2::disconnect() {
     sp<DataSource> dataSource, httpSource;
     {
         Mutex::Autolock _l(mLock);
@@ -549,11 +549,11 @@
     }
 }
 
-status_t NuPlayer2::GenericSource::feedMoreTSData() {
+status_t NuPlayer2::GenericSource2::feedMoreTSData() {
     return OK;
 }
 
-void NuPlayer2::GenericSource::sendCacheStats() {
+void NuPlayer2::GenericSource2::sendCacheStats() {
     int32_t kbps = 0;
     status_t err = UNKNOWN_ERROR;
 
@@ -569,7 +569,7 @@
     }
 }
 
-void NuPlayer2::GenericSource::onMessageReceived(const sp<AMessage> &msg) {
+void NuPlayer2::GenericSource2::onMessageReceived(const sp<AMessage> &msg) {
     Mutex::Autolock _l(mLock);
     switch (msg->what()) {
       case kWhatPrepareAsync:
@@ -686,7 +686,7 @@
     }
 }
 
-void NuPlayer2::GenericSource::fetchTextData(
+void NuPlayer2::GenericSource2::fetchTextData(
         uint32_t sendWhat,
         media_track_type type,
         int32_t curGen,
@@ -723,7 +723,7 @@
     mMediaClock->addTimer(msg2, subTimeUs);
 }
 
-void NuPlayer2::GenericSource::sendTextData(
+void NuPlayer2::GenericSource2::sendTextData(
         uint32_t what,
         media_track_type type,
         int32_t curGen,
@@ -759,7 +759,7 @@
     }
 }
 
-void NuPlayer2::GenericSource::sendGlobalTextData(
+void NuPlayer2::GenericSource2::sendGlobalTextData(
         uint32_t what,
         int32_t curGen,
         sp<AMessage> msg) {
@@ -790,12 +790,12 @@
     }
 }
 
-sp<MetaData> NuPlayer2::GenericSource::getFormatMeta(bool audio) {
+sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta(bool audio) {
     Mutex::Autolock _l(mLock);
     return getFormatMeta_l(audio);
 }
 
-sp<MetaData> NuPlayer2::GenericSource::getFormatMeta_l(bool audio) {
+sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta_l(bool audio) {
     sp<IMediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
 
     if (source == NULL) {
@@ -805,7 +805,7 @@
     return source->getFormat();
 }
 
-status_t NuPlayer2::GenericSource::dequeueAccessUnit(
+status_t NuPlayer2::GenericSource2::dequeueAccessUnit(
         bool audio, sp<ABuffer> *accessUnit) {
     Mutex::Autolock _l(mLock);
     // If has gone through stop/releaseDrm sequence, we no longer send down any buffer b/c
@@ -901,18 +901,18 @@
     return result;
 }
 
-status_t NuPlayer2::GenericSource::getDuration(int64_t *durationUs) {
+status_t NuPlayer2::GenericSource2::getDuration(int64_t *durationUs) {
     Mutex::Autolock _l(mLock);
     *durationUs = mDurationUs;
     return OK;
 }
 
-size_t NuPlayer2::GenericSource::getTrackCount() const {
+size_t NuPlayer2::GenericSource2::getTrackCount() const {
     Mutex::Autolock _l(mLock);
     return mSources.size();
 }
 
-sp<AMessage> NuPlayer2::GenericSource::getTrackInfo(size_t trackIndex) const {
+sp<AMessage> NuPlayer2::GenericSource2::getTrackInfo(size_t trackIndex) const {
     Mutex::Autolock _l(mLock);
     size_t trackCount = mSources.size();
     if (trackIndex >= trackCount) {
@@ -962,7 +962,7 @@
     return format;
 }
 
-ssize_t NuPlayer2::GenericSource::getSelectedTrack(media_track_type type) const {
+ssize_t NuPlayer2::GenericSource2::getSelectedTrack(media_track_type type) const {
     Mutex::Autolock _l(mLock);
     const Track *track = NULL;
     switch (type) {
@@ -989,7 +989,7 @@
     return -1;
 }
 
-status_t NuPlayer2::GenericSource::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
+status_t NuPlayer2::GenericSource2::selectTrack(size_t trackIndex, bool select, int64_t timeUs) {
     Mutex::Autolock _l(mLock);
     ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
 
@@ -1083,7 +1083,7 @@
     return INVALID_OPERATION;
 }
 
-status_t NuPlayer2::GenericSource::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
+status_t NuPlayer2::GenericSource2::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
     ALOGV("seekTo: %lld, %d", (long long)seekTimeUs, mode);
     sp<AMessage> msg = new AMessage(kWhatSeek, this);
     msg->setInt64("seekTimeUs", seekTimeUs);
@@ -1101,7 +1101,7 @@
     return err;
 }
 
-void NuPlayer2::GenericSource::onSeek(const sp<AMessage>& msg) {
+void NuPlayer2::GenericSource2::onSeek(const sp<AMessage>& msg) {
     int64_t seekTimeUs;
     int32_t mode;
     CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));
@@ -1116,7 +1116,7 @@
     response->postReply(replyID);
 }
 
-status_t NuPlayer2::GenericSource::doSeek(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
+status_t NuPlayer2::GenericSource2::doSeek(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
     if (mVideoTrack.mSource != NULL) {
         ++mVideoDataGeneration;
 
@@ -1150,7 +1150,7 @@
     return OK;
 }
 
-sp<ABuffer> NuPlayer2::GenericSource::mediaBufferToABuffer(
+sp<ABuffer> NuPlayer2::GenericSource2::mediaBufferToABuffer(
         MediaBuffer* mb,
         media_track_type trackType) {
     bool audio = trackType == MEDIA_TRACK_TYPE_AUDIO;
@@ -1248,7 +1248,7 @@
     return ab;
 }
 
-int32_t NuPlayer2::GenericSource::getDataGeneration(media_track_type type) const {
+int32_t NuPlayer2::GenericSource2::getDataGeneration(media_track_type type) const {
     int32_t generation = -1;
     switch (type) {
     case MEDIA_TRACK_TYPE_VIDEO:
@@ -1270,7 +1270,7 @@
     return generation;
 }
 
-void NuPlayer2::GenericSource::postReadBuffer(media_track_type trackType) {
+void NuPlayer2::GenericSource2::postReadBuffer(media_track_type trackType) {
     if ((mPendingReadBufferTypes & (1 << trackType)) == 0) {
         mPendingReadBufferTypes |= (1 << trackType);
         sp<AMessage> msg = new AMessage(kWhatReadBuffer, this);
@@ -1279,7 +1279,7 @@
     }
 }
 
-void NuPlayer2::GenericSource::onReadBuffer(const sp<AMessage>& msg) {
+void NuPlayer2::GenericSource2::onReadBuffer(const sp<AMessage>& msg) {
     int32_t tmpType;
     CHECK(msg->findInt32("trackType", &tmpType));
     media_track_type trackType = (media_track_type)tmpType;
@@ -1287,7 +1287,7 @@
     readBuffer(trackType);
 }
 
-void NuPlayer2::GenericSource::readBuffer(
+void NuPlayer2::GenericSource2::readBuffer(
         media_track_type trackType, int64_t seekTimeUs, MediaPlayer2SeekMode mode,
         int64_t *actualTimeUs, bool formatChange) {
     Track *track;
@@ -1460,7 +1460,7 @@
     }
 }
 
-void NuPlayer2::GenericSource::queueDiscontinuityIfNeeded(
+void NuPlayer2::GenericSource2::queueDiscontinuityIfNeeded(
         bool seeking, bool formatChange, media_track_type trackType, Track *track) {
     // formatChange && seeking: track whose source is changed during selection
     // formatChange && !seeking: track whose source is not changed during selection
@@ -1475,7 +1475,7 @@
     }
 }
 
-void NuPlayer2::GenericSource::notifyBufferingUpdate(int32_t percentage) {
+void NuPlayer2::GenericSource2::notifyBufferingUpdate(int32_t percentage) {
     // Buffering percent could go backward as it's estimated from remaining
     // data and last access time. This could cause the buffering position
     // drawn on media control to jitter slightly. Remember previously reported
@@ -1496,14 +1496,14 @@
     notify->post();
 }
 
-void NuPlayer2::GenericSource::schedulePollBuffering() {
+void NuPlayer2::GenericSource2::schedulePollBuffering() {
     sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
     msg->setInt32("generation", mPollBufferingGeneration);
     // Enquires buffering status every second.
     msg->post(1000000ll);
 }
 
-void NuPlayer2::GenericSource::onPollBuffering() {
+void NuPlayer2::GenericSource2::onPollBuffering() {
     status_t finalStatus = UNKNOWN_ERROR;
     int64_t cachedDurationUs = -1ll;
     ssize_t cachedDataRemaining = -1;
@@ -1554,7 +1554,7 @@
 }
 
 // Modular DRM
-status_t NuPlayer2::GenericSource::prepareDrm(
+status_t NuPlayer2::GenericSource2::prepareDrm(
         const uint8_t uuid[16],
         const Vector<uint8_t> &drmSessionId,
         sp<AMediaCryptoWrapper> *outCrypto) {
@@ -1611,7 +1611,7 @@
     return status;
 }
 
-status_t NuPlayer2::GenericSource::releaseDrm() {
+status_t NuPlayer2::GenericSource2::releaseDrm() {
     Mutex::Autolock _l(mLock);
     ALOGV("releaseDrm");
 
@@ -1627,7 +1627,7 @@
     return OK;
 }
 
-status_t NuPlayer2::GenericSource::checkDrmInfo()
+status_t NuPlayer2::GenericSource2::checkDrmInfo()
 {
     // clearing the flag at prepare in case the player is reused after stop/releaseDrm with the
     // same source without being reset (called by prepareAsync/initFromDataSource)
@@ -1661,7 +1661,7 @@
     return OK;
 }
 
-void NuPlayer2::GenericSource::signalBufferReturned(MediaBuffer *buffer)
+void NuPlayer2::GenericSource2::signalBufferReturned(MediaBuffer *buffer)
 {
     //ALOGV("signalBufferReturned %p  refCount: %d", buffer, buffer->localRefcount());
 
diff --git a/media/libmedia/nuplayer2/GenericSource.h b/media/libmedia/nuplayer2/GenericSource2.h
similarity index 93%
rename from media/libmedia/nuplayer2/GenericSource.h
rename to media/libmedia/nuplayer2/GenericSource2.h
index 5a71edb..2016304 100644
--- a/media/libmedia/nuplayer2/GenericSource.h
+++ b/media/libmedia/nuplayer2/GenericSource2.h
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef GENERIC_SOURCE_H_
+#ifndef GENERIC_SOURCE2_H_
 
-#define GENERIC_SOURCE_H_
+#define GENERIC_SOURCE2_H_
 
 #include "NuPlayer2.h"
 #include "NuPlayer2Source.h"
@@ -40,11 +40,11 @@
 struct MediaClock;
 struct NuCachedSource2;
 
-struct NuPlayer2::GenericSource : public NuPlayer2::Source,
-                                 public MediaBufferObserver // Modular DRM
+struct NuPlayer2::GenericSource2 : public NuPlayer2::Source,
+                                   public MediaBufferObserver // Modular DRM
 {
-    GenericSource(const sp<AMessage> &notify, bool uidValid, uid_t uid,
-                  const sp<MediaClock> &mediaClock);
+    GenericSource2(const sp<AMessage> &notify, bool uidValid, uid_t uid,
+                   const sp<MediaClock> &mediaClock);
 
     status_t setDataSource(
             const sp<MediaHTTPService> &httpService,
@@ -97,7 +97,7 @@
 
 
 protected:
-    virtual ~GenericSource();
+    virtual ~GenericSource2();
 
     virtual void onMessageReceived(const sp<AMessage> &msg);
 
@@ -240,9 +240,9 @@
 
     status_t checkDrmInfo();
 
-    DISALLOW_EVIL_CONSTRUCTORS(GenericSource);
+    DISALLOW_EVIL_CONSTRUCTORS(GenericSource2);
 };
 
 }  // namespace android
 
-#endif  // GENERIC_SOURCE_H_
+#endif  // GENERIC_SOURCE2_H_
diff --git a/media/libmedia/nuplayer2/HTTPLiveSource.cpp b/media/libmedia/nuplayer2/HTTPLiveSource2.cpp
similarity index 89%
rename from media/libmedia/nuplayer2/HTTPLiveSource.cpp
rename to media/libmedia/nuplayer2/HTTPLiveSource2.cpp
index e0e3df9..a61cacd 100644
--- a/media/libmedia/nuplayer2/HTTPLiveSource.cpp
+++ b/media/libmedia/nuplayer2/HTTPLiveSource2.cpp
@@ -15,10 +15,10 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "HTTPLiveSource"
+#define LOG_TAG "HTTPLiveSource2"
 #include <utils/Log.h>
 
-#include "HTTPLiveSource.h"
+#include "HTTPLiveSource2.h"
 
 #include "AnotherPacketSource.h"
 #include "LiveDataSource.h"
@@ -38,7 +38,7 @@
 
 namespace android {
 
-NuPlayer2::HTTPLiveSource::HTTPLiveSource(
+NuPlayer2::HTTPLiveSource2::HTTPLiveSource2(
         const sp<AMessage> &notify,
         const sp<MediaHTTPService> &httpService,
         const char *url,
@@ -69,7 +69,7 @@
     }
 }
 
-NuPlayer2::HTTPLiveSource::~HTTPLiveSource() {
+NuPlayer2::HTTPLiveSource2::~HTTPLiveSource2() {
     if (mLiveSession != NULL) {
         mLiveSession->disconnect();
 
@@ -82,14 +82,14 @@
     }
 }
 
-status_t NuPlayer2::HTTPLiveSource::getBufferingSettings(
+status_t NuPlayer2::HTTPLiveSource2::getBufferingSettings(
             BufferingSettings* buffering /* nonnull */) {
     *buffering = mBufferingSettings;
 
     return OK;
 }
 
-status_t NuPlayer2::HTTPLiveSource::setBufferingSettings(const BufferingSettings& buffering) {
+status_t NuPlayer2::HTTPLiveSource2::setBufferingSettings(const BufferingSettings& buffering) {
     mBufferingSettings = buffering;
 
     if (mLiveSession != NULL) {
@@ -99,7 +99,7 @@
     return OK;
 }
 
-void NuPlayer2::HTTPLiveSource::prepareAsync() {
+void NuPlayer2::HTTPLiveSource2::prepareAsync() {
     if (mLiveLooper == NULL) {
         mLiveLooper = new ALooper;
         mLiveLooper->setName("http live");
@@ -123,10 +123,10 @@
             mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
 }
 
-void NuPlayer2::HTTPLiveSource::start() {
+void NuPlayer2::HTTPLiveSource2::start() {
 }
 
-sp<MetaData> NuPlayer2::HTTPLiveSource::getFormatMeta(bool audio) {
+sp<MetaData> NuPlayer2::HTTPLiveSource2::getFormatMeta(bool audio) {
     sp<MetaData> meta;
     if (mLiveSession != NULL) {
         mLiveSession->getStreamFormatMeta(
@@ -138,7 +138,7 @@
     return meta;
 }
 
-sp<AMessage> NuPlayer2::HTTPLiveSource::getFormat(bool audio) {
+sp<AMessage> NuPlayer2::HTTPLiveSource2::getFormat(bool audio) {
     sp<MetaData> meta;
     status_t err = -EWOULDBLOCK;
     if (mLiveSession != NULL) {
@@ -161,11 +161,11 @@
     return format;
 }
 
-status_t NuPlayer2::HTTPLiveSource::feedMoreTSData() {
+status_t NuPlayer2::HTTPLiveSource2::feedMoreTSData() {
     return OK;
 }
 
-status_t NuPlayer2::HTTPLiveSource::dequeueAccessUnit(
+status_t NuPlayer2::HTTPLiveSource2::dequeueAccessUnit(
         bool audio, sp<ABuffer> *accessUnit) {
     return mLiveSession->dequeueAccessUnit(
             audio ? LiveSession::STREAMTYPE_AUDIO
@@ -173,19 +173,19 @@
             accessUnit);
 }
 
-status_t NuPlayer2::HTTPLiveSource::getDuration(int64_t *durationUs) {
+status_t NuPlayer2::HTTPLiveSource2::getDuration(int64_t *durationUs) {
     return mLiveSession->getDuration(durationUs);
 }
 
-size_t NuPlayer2::HTTPLiveSource::getTrackCount() const {
+size_t NuPlayer2::HTTPLiveSource2::getTrackCount() const {
     return mLiveSession->getTrackCount();
 }
 
-sp<AMessage> NuPlayer2::HTTPLiveSource::getTrackInfo(size_t trackIndex) const {
+sp<AMessage> NuPlayer2::HTTPLiveSource2::getTrackInfo(size_t trackIndex) const {
     return mLiveSession->getTrackInfo(trackIndex);
 }
 
-ssize_t NuPlayer2::HTTPLiveSource::getSelectedTrack(media_track_type type) const {
+ssize_t NuPlayer2::HTTPLiveSource2::getSelectedTrack(media_track_type type) const {
     if (mLiveSession == NULL) {
         return -1;
     } else if (type == MEDIA_TRACK_TYPE_METADATA) {
@@ -197,7 +197,7 @@
     }
 }
 
-status_t NuPlayer2::HTTPLiveSource::selectTrack(size_t trackIndex, bool select, int64_t /*timeUs*/) {
+status_t NuPlayer2::HTTPLiveSource2::selectTrack(size_t trackIndex, bool select, int64_t /*timeUs*/) {
     if (mLiveSession == NULL) {
         return INVALID_OPERATION;
     }
@@ -239,7 +239,7 @@
     return (err == OK || err == BAD_VALUE) ? (status_t)OK : err;
 }
 
-status_t NuPlayer2::HTTPLiveSource::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
+status_t NuPlayer2::HTTPLiveSource2::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
     if (mLiveSession->isSeekable()) {
         return mLiveSession->seekTo(seekTimeUs, mode);
     } else {
@@ -247,7 +247,7 @@
     }
 }
 
-void NuPlayer2::HTTPLiveSource::pollForRawData(
+void NuPlayer2::HTTPLiveSource2::pollForRawData(
         const sp<AMessage> &msg, int32_t currentGeneration,
         LiveSession::StreamType fetchType, int32_t pushWhat) {
 
@@ -290,7 +290,7 @@
     msg->post(1000000ll);
 }
 
-void NuPlayer2::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) {
+void NuPlayer2::HTTPLiveSource2::onMessageReceived(const sp<AMessage> &msg) {
     switch (msg->what()) {
         case kWhatSessionNotify:
         {
@@ -328,7 +328,7 @@
     }
 }
 
-void NuPlayer2::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) {
+void NuPlayer2::HTTPLiveSource2::onSessionNotify(const sp<AMessage> &msg) {
     int32_t what;
     CHECK(msg->findInt32("what", &what));
 
diff --git a/media/libmedia/nuplayer2/HTTPLiveSource.h b/media/libmedia/nuplayer2/HTTPLiveSource2.h
similarity index 91%
rename from media/libmedia/nuplayer2/HTTPLiveSource.h
rename to media/libmedia/nuplayer2/HTTPLiveSource2.h
index 7b6a312..97d3653 100644
--- a/media/libmedia/nuplayer2/HTTPLiveSource.h
+++ b/media/libmedia/nuplayer2/HTTPLiveSource2.h
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef HTTP_LIVE_SOURCE_H_
+#ifndef HTTP_LIVE_SOURCE2_H_
 
-#define HTTP_LIVE_SOURCE_H_
+#define HTTP_LIVE_SOURCE2_H_
 
 #include "NuPlayer2.h"
 #include "NuPlayer2Source.h"
@@ -27,8 +27,8 @@
 
 struct LiveSession;
 
-struct NuPlayer2::HTTPLiveSource : public NuPlayer2::Source {
-    HTTPLiveSource(
+struct NuPlayer2::HTTPLiveSource2 : public NuPlayer2::Source {
+    HTTPLiveSource2(
             const sp<AMessage> &notify,
             const sp<MediaHTTPService> &httpService,
             const char *url,
@@ -56,7 +56,7 @@
             MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC) override;
 
 protected:
-    virtual ~HTTPLiveSource();
+    virtual ~HTTPLiveSource2();
 
     virtual void onMessageReceived(const sp<AMessage> &msg);
 
@@ -91,9 +91,9 @@
             const sp<AMessage> &msg, int32_t currentGeneration,
             LiveSession::StreamType fetchType, int32_t pushWhat);
 
-    DISALLOW_EVIL_CONSTRUCTORS(HTTPLiveSource);
+    DISALLOW_EVIL_CONSTRUCTORS(HTTPLiveSource2);
 };
 
 }  // namespace android
 
-#endif  // HTTP_LIVE_SOURCE_H_
+#endif  // HTTP_LIVE_SOURCE2_H_
diff --git a/media/libmedia/nuplayer2/NuPlayer2.cpp b/media/libmedia/nuplayer2/NuPlayer2.cpp
index 35e20e8..65e0957 100644
--- a/media/libmedia/nuplayer2/NuPlayer2.cpp
+++ b/media/libmedia/nuplayer2/NuPlayer2.cpp
@@ -23,7 +23,7 @@
 
 #include "NuPlayer2.h"
 
-#include "HTTPLiveSource.h"
+#include "HTTPLiveSource2.h"
 #include "NuPlayer2CCDecoder.h"
 #include "NuPlayer2Decoder.h"
 #include "NuPlayer2DecoderBase.h"
@@ -31,9 +31,8 @@
 #include "NuPlayer2Driver.h"
 #include "NuPlayer2Renderer.h"
 #include "NuPlayer2Source.h"
-#include "RTSPSource.h"
-#include "StreamingSource.h"
-#include "GenericSource.h"
+#include "RTSPSource2.h"
+#include "GenericSource2.h"
 #include "TextDescriptions.h"
 
 #include "ATSParser.h"
@@ -291,27 +290,27 @@
             KeyedVector<String8, String8> *headers = &(dsd->mHeaders);
 
             if (IsHTTPLiveURL(url)) {
-                source = new HTTPLiveSource(notify, httpService, url, headers);
-                ALOGV("setDataSourceAsync HTTPLiveSource %s", url);
+                source = new HTTPLiveSource2(notify, httpService, url, headers);
+                ALOGV("setDataSourceAsync HTTPLiveSource2 %s", url);
                 mDataSourceType = DATA_SOURCE_TYPE_HTTP_LIVE;
             } else if (!strncasecmp(url, "rtsp://", 7)) {
-                source = new RTSPSource(
+                source = new RTSPSource2(
                         notify, httpService, url, headers, mUIDValid, mUID);
-                ALOGV("setDataSourceAsync RTSPSource %s", url);
+                ALOGV("setDataSourceAsync RTSPSource2 %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(
+                source = new RTSPSource2(
                         notify, httpService, url, headers, mUIDValid, mUID, true);
-                ALOGV("setDataSourceAsync RTSPSource http/https/.sdp %s", url);
+                ALOGV("setDataSourceAsync RTSPSource2 http/https/.sdp %s", url);
                 mDataSourceType = DATA_SOURCE_TYPE_RTSP;
             } else {
-                ALOGV("setDataSourceAsync GenericSource %s", url);
+                ALOGV("setDataSourceAsync GenericSource2 %s", url);
 
-                sp<GenericSource> genericSource =
-                        new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+                sp<GenericSource2> genericSource =
+                        new GenericSource2(notify, mUIDValid, mUID, mMediaClock);
 
                 status_t err = genericSource->setDataSource(httpService, url, headers);
 
@@ -329,8 +328,8 @@
 
         case DataSourceDesc::TYPE_FD:
         {
-            sp<GenericSource> genericSource =
-                    new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+            sp<GenericSource2> genericSource =
+                    new GenericSource2(notify, mUIDValid, mUID, mMediaClock);
 
             ALOGV("setDataSourceAsync fd %d/%lld/%lld source: %p",
                   dsd->mFD, (long long)dsd->mFDOffset, (long long)dsd->mFDLength, source.get());
@@ -350,8 +349,8 @@
 
         case DataSourceDesc::TYPE_CALLBACK:
         {
-            sp<GenericSource> genericSource =
-                    new GenericSource(notify, mUIDValid, mUID, mMediaClock);
+            sp<GenericSource2> genericSource =
+                    new GenericSource2(notify, mUIDValid, mUID, mMediaClock);
             status_t err = genericSource->setDataSource(dsd->mCallbackSource);
 
             if (err != OK) {
diff --git a/media/libmedia/nuplayer2/NuPlayer2.h b/media/libmedia/nuplayer2/NuPlayer2.h
index 0764ec3..1d74b55 100644
--- a/media/libmedia/nuplayer2/NuPlayer2.h
+++ b/media/libmedia/nuplayer2/NuPlayer2.h
@@ -106,11 +106,10 @@
     struct DecoderBase;
     struct DecoderPassThrough;
     struct CCDecoder;
-    struct GenericSource;
-    struct HTTPLiveSource;
+    struct GenericSource2;
+    struct HTTPLiveSource2;
     struct Renderer;
-    struct RTSPSource;
-    struct StreamingSource;
+    struct RTSPSource2;
     struct Action;
     struct SeekAction;
     struct SetSurfaceAction;
diff --git a/media/libmedia/nuplayer2/NuPlayer2StreamListener.cpp b/media/libmedia/nuplayer2/NuPlayer2StreamListener.cpp
deleted file mode 100644
index 0769711..0000000
--- a/media/libmedia/nuplayer2/NuPlayer2StreamListener.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright 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 "NuPlayer2StreamListener"
-#include <utils/Log.h>
-
-#include "NuPlayer2StreamListener.h"
-
-#include <binder/MemoryDealer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/MediaErrors.h>
-
-namespace android {
-
-NuPlayer2::StreamListener::StreamListener(
-        const sp<IStreamSource> &source,
-        const sp<AHandler> &targetHandler)
-    : mSource(source),
-      mTargetHandler(targetHandler),
-      mEOS(false),
-      mSendDataNotification(true) {
-    mSource->setListener(this);
-
-    mMemoryDealer = new MemoryDealer(kNumBuffers * kBufferSize);
-    for (size_t i = 0; i < kNumBuffers; ++i) {
-        sp<IMemory> mem = mMemoryDealer->allocate(kBufferSize);
-        CHECK(mem != NULL);
-
-        mBuffers.push(mem);
-    }
-    mSource->setBuffers(mBuffers);
-}
-
-void NuPlayer2::StreamListener::start() {
-    for (size_t i = 0; i < kNumBuffers; ++i) {
-        mSource->onBufferAvailable(i);
-    }
-}
-
-void NuPlayer2::StreamListener::queueBuffer(size_t index, size_t size) {
-    QueueEntry entry;
-    entry.mIsCommand = false;
-    entry.mIndex = index;
-    entry.mSize = size;
-    entry.mOffset = 0;
-
-    Mutex::Autolock autoLock(mLock);
-    mQueue.push_back(entry);
-
-    if (mSendDataNotification) {
-        mSendDataNotification = false;
-
-        if (mTargetHandler != NULL) {
-            (new AMessage(kWhatMoreDataQueued, mTargetHandler))->post();
-        }
-    }
-}
-
-void NuPlayer2::StreamListener::issueCommand(
-        Command cmd, bool synchronous, const sp<AMessage> &extra) {
-    CHECK(!synchronous);
-
-    QueueEntry entry;
-    entry.mIsCommand = true;
-    entry.mCommand = cmd;
-    entry.mExtra = extra;
-
-    Mutex::Autolock autoLock(mLock);
-    mQueue.push_back(entry);
-
-    if (mSendDataNotification) {
-        mSendDataNotification = false;
-
-        if (mTargetHandler != NULL) {
-            (new AMessage(kWhatMoreDataQueued, mTargetHandler))->post();
-        }
-    }
-}
-
-ssize_t NuPlayer2::StreamListener::read(
-        void *data, size_t size, sp<AMessage> *extra) {
-    CHECK_GT(size, 0u);
-
-    extra->clear();
-
-    Mutex::Autolock autoLock(mLock);
-
-    if (mEOS) {
-        return 0;
-    }
-
-    if (mQueue.empty()) {
-        mSendDataNotification = true;
-
-        return -EWOULDBLOCK;
-    }
-
-    QueueEntry *entry = &*mQueue.begin();
-
-    if (entry->mIsCommand) {
-        switch (entry->mCommand) {
-            case EOS:
-            {
-                mQueue.erase(mQueue.begin());
-                entry = NULL;
-
-                mEOS = true;
-                return 0;
-            }
-
-            case DISCONTINUITY:
-            {
-                *extra = entry->mExtra;
-
-                mQueue.erase(mQueue.begin());
-                entry = NULL;
-
-                return INFO_DISCONTINUITY;
-            }
-
-            default:
-                TRESPASS();
-                break;
-        }
-    }
-
-    size_t copy = entry->mSize;
-    if (copy > size) {
-        copy = size;
-    }
-
-    if (entry->mIndex >= mBuffers.size()) {
-        return ERROR_MALFORMED;
-    }
-
-    sp<IMemory> mem = mBuffers.editItemAt(entry->mIndex);
-    if (mem == NULL || mem->size() < copy || mem->size() - copy < entry->mOffset) {
-        return ERROR_MALFORMED;
-    }
-
-    memcpy(data,
-           (const uint8_t *)mem->pointer()
-            + entry->mOffset,
-           copy);
-
-    entry->mOffset += copy;
-    entry->mSize -= copy;
-
-    if (entry->mSize == 0) {
-        mSource->onBufferAvailable(entry->mIndex);
-        mQueue.erase(mQueue.begin());
-        entry = NULL;
-    }
-
-    return copy;
-}
-
-}  // namespace android
diff --git a/media/libmedia/nuplayer2/NuPlayer2StreamListener.h b/media/libmedia/nuplayer2/NuPlayer2StreamListener.h
deleted file mode 100644
index 4327b24..0000000
--- a/media/libmedia/nuplayer2/NuPlayer2StreamListener.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 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 NUPLAYER2_STREAM_LISTENER_H_
-
-#define NUPLAYER2_STREAM_LISTENER_H_
-
-#include "NuPlayer2.h"
-
-#include <media/IStreamSource.h>
-
-namespace android {
-
-class MemoryDealer;
-
-struct NuPlayer2::StreamListener : public BnStreamListener {
-    StreamListener(
-            const sp<IStreamSource> &source,
-            const sp<AHandler> &targetHandler);
-
-    virtual void queueBuffer(size_t index, size_t size);
-
-    virtual void issueCommand(
-            Command cmd, bool synchronous, const sp<AMessage> &extra);
-
-    void start();
-    ssize_t read(void *data, size_t size, sp<AMessage> *extra);
-
-private:
-    enum {
-        kNumBuffers = 8,
-        kBufferSize = 188 * 10
-    };
-
-    struct QueueEntry {
-        bool mIsCommand;
-
-        size_t mIndex;
-        size_t mSize;
-        size_t mOffset;
-
-        Command mCommand;
-        sp<AMessage> mExtra;
-    };
-
-    Mutex mLock;
-
-    sp<IStreamSource> mSource;
-    sp<AHandler> mTargetHandler;
-    sp<MemoryDealer> mMemoryDealer;
-    Vector<sp<IMemory> > mBuffers;
-    List<QueueEntry> mQueue;
-    bool mEOS;
-    bool mSendDataNotification;
-
-    DISALLOW_EVIL_CONSTRUCTORS(StreamListener);
-};
-
-}  // namespace android
-
-#endif // NUPLAYER2_STREAM_LISTENER_H_
diff --git a/media/libmedia/nuplayer2/RTSPSource.cpp b/media/libmedia/nuplayer2/RTSPSource2.cpp
similarity index 91%
rename from media/libmedia/nuplayer2/RTSPSource.cpp
rename to media/libmedia/nuplayer2/RTSPSource2.cpp
index 3f6966d..8b67ae5 100644
--- a/media/libmedia/nuplayer2/RTSPSource.cpp
+++ b/media/libmedia/nuplayer2/RTSPSource2.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright 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.
@@ -15,10 +15,10 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "RTSPSource"
+#define LOG_TAG "RTSPSource2"
 #include <utils/Log.h>
 
-#include "RTSPSource.h"
+#include "RTSPSource2.h"
 
 #include "AnotherPacketSource.h"
 #include "MyHandler.h"
@@ -38,7 +38,7 @@
 //static const int kStartServerMarkMs =  5000;
 static const int kOverflowMarkMs    = 10000;  // 10 seconds
 
-NuPlayer2::RTSPSource::RTSPSource(
+NuPlayer2::RTSPSource2::RTSPSource2(
         const sp<AMessage> &notify,
         const sp<MediaHTTPService> &httpService,
         const char *url,
@@ -78,27 +78,27 @@
     }
 }
 
-NuPlayer2::RTSPSource::~RTSPSource() {
+NuPlayer2::RTSPSource2::~RTSPSource2() {
     if (mLooper != NULL) {
         mLooper->unregisterHandler(id());
         mLooper->stop();
     }
 }
 
-status_t NuPlayer2::RTSPSource::getBufferingSettings(
+status_t NuPlayer2::RTSPSource2::getBufferingSettings(
             BufferingSettings* buffering /* nonnull */) {
     Mutex::Autolock _l(mBufferingSettingsLock);
     *buffering = mBufferingSettings;
     return OK;
 }
 
-status_t NuPlayer2::RTSPSource::setBufferingSettings(const BufferingSettings& buffering) {
+status_t NuPlayer2::RTSPSource2::setBufferingSettings(const BufferingSettings& buffering) {
     Mutex::Autolock _l(mBufferingSettingsLock);
     mBufferingSettings = buffering;
     return OK;
 }
 
-void NuPlayer2::RTSPSource::prepareAsync() {
+void NuPlayer2::RTSPSource2::prepareAsync() {
     if (mIsSDP && mHTTPService == NULL) {
         notifyPrepared(BAD_VALUE);
         return;
@@ -137,10 +137,10 @@
     startBufferingIfNecessary();
 }
 
-void NuPlayer2::RTSPSource::start() {
+void NuPlayer2::RTSPSource2::start() {
 }
 
-void NuPlayer2::RTSPSource::stop() {
+void NuPlayer2::RTSPSource2::stop() {
     if (mLooper == NULL) {
         return;
     }
@@ -150,12 +150,12 @@
     msg->postAndAwaitResponse(&dummy);
 }
 
-status_t NuPlayer2::RTSPSource::feedMoreTSData() {
+status_t NuPlayer2::RTSPSource2::feedMoreTSData() {
     Mutex::Autolock _l(mBufferingLock);
     return mFinalResult;
 }
 
-sp<MetaData> NuPlayer2::RTSPSource::getFormatMeta(bool audio) {
+sp<MetaData> NuPlayer2::RTSPSource2::getFormatMeta(bool audio) {
     sp<AnotherPacketSource> source = getSource(audio);
 
     if (source == NULL) {
@@ -165,7 +165,7 @@
     return source->getFormat();
 }
 
-bool NuPlayer2::RTSPSource::haveSufficientDataOnAllTracks() {
+bool NuPlayer2::RTSPSource2::haveSufficientDataOnAllTracks() {
     // We're going to buffer at least 2 secs worth data on all tracks before
     // starting playback (both at startup and after a seek).
 
@@ -201,7 +201,7 @@
     return true;
 }
 
-status_t NuPlayer2::RTSPSource::dequeueAccessUnit(
+status_t NuPlayer2::RTSPSource2::dequeueAccessUnit(
         bool audio, sp<ABuffer> *accessUnit) {
     if (!stopBufferingIfNecessary()) {
         return -EWOULDBLOCK;
@@ -253,7 +253,7 @@
     return source->dequeueAccessUnit(accessUnit);
 }
 
-sp<AnotherPacketSource> NuPlayer2::RTSPSource::getSource(bool audio) {
+sp<AnotherPacketSource> NuPlayer2::RTSPSource2::getSource(bool audio) {
     if (mTSParser != NULL) {
         sp<MediaSource> source = mTSParser->getSource(
                 audio ? ATSParser::AUDIO : ATSParser::VIDEO);
@@ -264,7 +264,7 @@
     return audio ? mAudioTrack : mVideoTrack;
 }
 
-void NuPlayer2::RTSPSource::setEOSTimeout(bool audio, int64_t timeout) {
+void NuPlayer2::RTSPSource2::setEOSTimeout(bool audio, int64_t timeout) {
     if (audio) {
         mEOSTimeoutAudio = timeout;
     } else {
@@ -272,7 +272,7 @@
     }
 }
 
-status_t NuPlayer2::RTSPSource::getDuration(int64_t *durationUs) {
+status_t NuPlayer2::RTSPSource2::getDuration(int64_t *durationUs) {
     *durationUs = -1ll;
 
     int64_t audioDurationUs;
@@ -294,7 +294,7 @@
     return OK;
 }
 
-status_t NuPlayer2::RTSPSource::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
+status_t NuPlayer2::RTSPSource2::seekTo(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
     sp<AMessage> msg = new AMessage(kWhatPerformSeek, this);
     msg->setInt32("generation", ++mSeekGeneration);
     msg->setInt64("timeUs", seekTimeUs);
@@ -309,7 +309,7 @@
     return err;
 }
 
-void NuPlayer2::RTSPSource::performSeek(int64_t seekTimeUs) {
+void NuPlayer2::RTSPSource2::performSeek(int64_t seekTimeUs) {
     if (mState != CONNECTED) {
         finishSeek(INVALID_OPERATION);
         return;
@@ -320,12 +320,12 @@
     mEOSPending = false;
 }
 
-void NuPlayer2::RTSPSource::schedulePollBuffering() {
+void NuPlayer2::RTSPSource2::schedulePollBuffering() {
     sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
     msg->post(1000000ll); // 1 second intervals
 }
 
-void NuPlayer2::RTSPSource::checkBuffering(
+void NuPlayer2::RTSPSource2::checkBuffering(
         bool *prepared, bool *underflow, bool *overflow, bool *startServer, bool *finished) {
     size_t numTracks = mTracks.size();
     size_t preparedCount, underflowCount, overflowCount, startCount, finishedCount;
@@ -383,7 +383,7 @@
     *finished    = (finishedCount > 0);
 }
 
-void NuPlayer2::RTSPSource::onPollBuffering() {
+void NuPlayer2::RTSPSource2::onPollBuffering() {
     bool prepared, underflow, overflow, startServer, finished;
     checkBuffering(&prepared, &underflow, &overflow, &startServer, &finished);
 
@@ -415,7 +415,7 @@
     schedulePollBuffering();
 }
 
-void NuPlayer2::RTSPSource::signalSourceEOS(status_t result) {
+void NuPlayer2::RTSPSource2::signalSourceEOS(status_t result) {
     const bool audio = true;
     const bool video = false;
 
@@ -430,7 +430,7 @@
     }
 }
 
-bool NuPlayer2::RTSPSource::sourceReachedEOS(bool audio) {
+bool NuPlayer2::RTSPSource2::sourceReachedEOS(bool audio) {
     sp<AnotherPacketSource> source = getSource(audio);
     status_t finalResult;
     return (source != NULL &&
@@ -438,14 +438,14 @@
             finalResult == ERROR_END_OF_STREAM);
 }
 
-bool NuPlayer2::RTSPSource::sourceNearEOS(bool audio) {
+bool NuPlayer2::RTSPSource2::sourceNearEOS(bool audio) {
     sp<AnotherPacketSource> source = getSource(audio);
     int64_t mediaDurationUs = 0;
     getDuration(&mediaDurationUs);
     return (source != NULL && source->isFinished(mediaDurationUs));
 }
 
-void NuPlayer2::RTSPSource::onSignalEOS(const sp<AMessage> &msg) {
+void NuPlayer2::RTSPSource2::onSignalEOS(const sp<AMessage> &msg) {
     int32_t generation;
     CHECK(msg->findInt32("generation", &generation));
 
@@ -459,7 +459,7 @@
     }
 }
 
-void NuPlayer2::RTSPSource::postSourceEOSIfNecessary() {
+void NuPlayer2::RTSPSource2::postSourceEOSIfNecessary() {
     const bool audio = true;
     const bool video = false;
     // If a source has detected near end, give it some time to retrieve more
@@ -474,7 +474,7 @@
     }
 }
 
-void NuPlayer2::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
+void NuPlayer2::RTSPSource2::onMessageReceived(const sp<AMessage> &msg) {
     if (msg->what() == kWhatDisconnect) {
         sp<AReplyToken> replyID;
         CHECK(msg->senderAwaitsResponse(&replyID));
@@ -722,7 +722,7 @@
     }
 }
 
-void NuPlayer2::RTSPSource::onConnected() {
+void NuPlayer2::RTSPSource2::onConnected() {
     CHECK(mAudioTrack == NULL);
     CHECK(mVideoTrack == NULL);
 
@@ -770,7 +770,7 @@
     mState = CONNECTED;
 }
 
-void NuPlayer2::RTSPSource::onSDPLoaded(const sp<AMessage> &msg) {
+void NuPlayer2::RTSPSource2::onSDPLoaded(const sp<AMessage> &msg) {
     status_t err;
     CHECK(msg->findInt32("result", &err));
 
@@ -816,7 +816,7 @@
     }
 }
 
-void NuPlayer2::RTSPSource::onDisconnected(const sp<AMessage> &msg) {
+void NuPlayer2::RTSPSource2::onDisconnected(const sp<AMessage> &msg) {
     if (mState == DISCONNECTED) {
         return;
     }
@@ -842,7 +842,7 @@
     }
 }
 
-void NuPlayer2::RTSPSource::finishDisconnectIfPossible() {
+void NuPlayer2::RTSPSource2::finishDisconnectIfPossible() {
     if (mState != DISCONNECTED) {
         if (mHandler != NULL) {
             mHandler->disconnect();
@@ -856,12 +856,12 @@
     mDisconnectReplyID = 0;
 }
 
-void NuPlayer2::RTSPSource::setError(status_t err) {
+void NuPlayer2::RTSPSource2::setError(status_t err) {
     Mutex::Autolock _l(mBufferingLock);
     mFinalResult = err;
 }
 
-void NuPlayer2::RTSPSource::startBufferingIfNecessary() {
+void NuPlayer2::RTSPSource2::startBufferingIfNecessary() {
     Mutex::Autolock _l(mBufferingLock);
 
     if (!mBuffering) {
@@ -873,7 +873,7 @@
     }
 }
 
-bool NuPlayer2::RTSPSource::stopBufferingIfNecessary() {
+bool NuPlayer2::RTSPSource2::stopBufferingIfNecessary() {
     Mutex::Autolock _l(mBufferingLock);
 
     if (mBuffering) {
@@ -891,7 +891,7 @@
     return true;
 }
 
-void NuPlayer2::RTSPSource::finishSeek(status_t err) {
+void NuPlayer2::RTSPSource2::finishSeek(status_t err) {
     if (mSeekReplyID == NULL) {
         return;
     }
diff --git a/media/libmedia/nuplayer2/RTSPSource.h b/media/libmedia/nuplayer2/RTSPSource2.h
similarity index 94%
rename from media/libmedia/nuplayer2/RTSPSource.h
rename to media/libmedia/nuplayer2/RTSPSource2.h
index 9bce473..739bd53 100644
--- a/media/libmedia/nuplayer2/RTSPSource.h
+++ b/media/libmedia/nuplayer2/RTSPSource2.h
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#ifndef RTSP_SOURCE_H_
+#ifndef RTSP_SOURCE2_H_
 
-#define RTSP_SOURCE_H_
+#define RTSP_SOURCE2_H_
 
 #include "NuPlayer2Source.h"
 
@@ -30,8 +30,8 @@
 struct MyHandler;
 struct SDPLoader;
 
-struct NuPlayer2::RTSPSource : public NuPlayer2::Source {
-    RTSPSource(
+struct NuPlayer2::RTSPSource2 : public NuPlayer2::Source {
+    RTSPSource2(
             const sp<AMessage> &notify,
             const sp<MediaHTTPService> &httpService,
             const char *url,
@@ -60,7 +60,7 @@
     void onMessageReceived(const sp<AMessage> &msg);
 
 protected:
-    virtual ~RTSPSource();
+    virtual ~RTSPSource2();
 
     virtual sp<MetaData> getFormatMeta(bool audio);
 
@@ -161,9 +161,9 @@
     bool sourceNearEOS(bool audio);
     bool sourceReachedEOS(bool audio);
 
-    DISALLOW_EVIL_CONSTRUCTORS(RTSPSource);
+    DISALLOW_EVIL_CONSTRUCTORS(RTSPSource2);
 };
 
 }  // namespace android
 
-#endif  // RTSP_SOURCE_H_
+#endif  // RTSP_SOURCE2_H_
diff --git a/media/libmedia/nuplayer2/StreamingSource.cpp b/media/libmedia/nuplayer2/StreamingSource.cpp
deleted file mode 100644
index 1c370b6..0000000
--- a/media/libmedia/nuplayer2/StreamingSource.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * Copyright (C) 2010 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 "StreamingSource"
-#include <utils/Log.h>
-
-#include "StreamingSource.h"
-
-#include "ATSParser.h"
-#include "AnotherPacketSource.h"
-#include "NuPlayer2StreamListener.h"
-
-#include <media/MediaSource.h>
-#include <media/stagefright/foundation/ABuffer.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/foundation/AMessage.h>
-#include <media/stagefright/foundation/MediaKeys.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/Utils.h>
-
-namespace android {
-
-const int32_t kNumListenerQueuePackets = 80;
-
-NuPlayer2::StreamingSource::StreamingSource(
-        const sp<AMessage> &notify,
-        const sp<IStreamSource> &source)
-    : Source(notify),
-      mSource(source),
-      mFinalResult(OK),
-      mBuffering(false) {
-}
-
-NuPlayer2::StreamingSource::~StreamingSource() {
-    if (mLooper != NULL) {
-        mLooper->unregisterHandler(id());
-        mLooper->stop();
-    }
-}
-
-status_t NuPlayer2::StreamingSource::getBufferingSettings(
-        BufferingSettings *buffering /* nonnull */) {
-    *buffering = BufferingSettings();
-    return OK;
-}
-
-status_t NuPlayer2::StreamingSource::setBufferingSettings(
-        const BufferingSettings & /* buffering */) {
-    return OK;
-}
-
-void NuPlayer2::StreamingSource::prepareAsync() {
-    if (mLooper == NULL) {
-        mLooper = new ALooper;
-        mLooper->setName("streaming");
-        mLooper->start();
-
-        mLooper->registerHandler(this);
-    }
-
-    notifyVideoSizeChanged();
-    notifyFlagsChanged(0);
-    notifyPrepared();
-}
-
-void NuPlayer2::StreamingSource::start() {
-    mStreamListener = new StreamListener(mSource, NULL);
-
-    uint32_t sourceFlags = mSource->flags();
-
-    uint32_t parserFlags = ATSParser::TS_TIMESTAMPS_ARE_ABSOLUTE;
-    if (sourceFlags & IStreamSource::kFlagAlignedVideoData) {
-        parserFlags |= ATSParser::ALIGNED_VIDEO_DATA;
-    }
-
-    mTSParser = new ATSParser(parserFlags);
-
-    mStreamListener->start();
-
-    postReadBuffer();
-}
-
-status_t NuPlayer2::StreamingSource::feedMoreTSData() {
-    return postReadBuffer();
-}
-
-void NuPlayer2::StreamingSource::onReadBuffer() {
-    for (int32_t i = 0; i < kNumListenerQueuePackets; ++i) {
-        char buffer[188];
-        sp<AMessage> extra;
-        ssize_t n = mStreamListener->read(buffer, sizeof(buffer), &extra);
-
-        if (n == 0) {
-            ALOGI("input data EOS reached.");
-            mTSParser->signalEOS(ERROR_END_OF_STREAM);
-            setError(ERROR_END_OF_STREAM);
-            break;
-        } else if (n == INFO_DISCONTINUITY) {
-            int32_t type = ATSParser::DISCONTINUITY_TIME;
-
-            int32_t mask;
-            if (extra != NULL
-                    && extra->findInt32(
-                        kIStreamListenerKeyDiscontinuityMask, &mask)) {
-                if (mask == 0) {
-                    ALOGE("Client specified an illegal discontinuity type.");
-                    setError(ERROR_UNSUPPORTED);
-                    break;
-                }
-
-                type = mask;
-            }
-
-            mTSParser->signalDiscontinuity(
-                    (ATSParser::DiscontinuityType)type, extra);
-        } else if (n < 0) {
-            break;
-        } else {
-            if (buffer[0] == 0x00) {
-                // XXX legacy
-
-                if (extra == NULL) {
-                    extra = new AMessage;
-                }
-
-                uint8_t type = buffer[1];
-
-                if (type & 2) {
-                    int64_t mediaTimeUs;
-                    memcpy(&mediaTimeUs, &buffer[2], sizeof(mediaTimeUs));
-
-                    extra->setInt64(kATSParserKeyMediaTimeUs, mediaTimeUs);
-                }
-
-                mTSParser->signalDiscontinuity(
-                        ((type & 1) == 0)
-                            ? ATSParser::DISCONTINUITY_TIME
-                            : ATSParser::DISCONTINUITY_FORMATCHANGE,
-                        extra);
-            } else {
-                status_t err = mTSParser->feedTSPacket(buffer, sizeof(buffer));
-
-                if (err != OK) {
-                    ALOGE("TS Parser returned error %d", err);
-
-                    mTSParser->signalEOS(err);
-                    setError(err);
-                    break;
-                }
-            }
-        }
-    }
-}
-
-status_t NuPlayer2::StreamingSource::postReadBuffer() {
-    {
-        Mutex::Autolock _l(mBufferingLock);
-        if (mFinalResult != OK) {
-            return mFinalResult;
-        }
-        if (mBuffering) {
-            return OK;
-        }
-        mBuffering = true;
-    }
-
-    (new AMessage(kWhatReadBuffer, this))->post();
-    return OK;
-}
-
-bool NuPlayer2::StreamingSource::haveSufficientDataOnAllTracks() {
-    // We're going to buffer at least 2 secs worth data on all tracks before
-    // starting playback (both at startup and after a seek).
-
-    static const int64_t kMinDurationUs = 2000000ll;
-
-    sp<AnotherPacketSource> audioTrack = getSource(true /*audio*/);
-    sp<AnotherPacketSource> videoTrack = getSource(false /*audio*/);
-
-    status_t err;
-    int64_t durationUs;
-    if (audioTrack != NULL
-            && (durationUs = audioTrack->getBufferedDurationUs(&err))
-                    < kMinDurationUs
-            && err == OK) {
-        ALOGV("audio track doesn't have enough data yet. (%.2f secs buffered)",
-              durationUs / 1E6);
-        return false;
-    }
-
-    if (videoTrack != NULL
-            && (durationUs = videoTrack->getBufferedDurationUs(&err))
-                    < kMinDurationUs
-            && err == OK) {
-        ALOGV("video track doesn't have enough data yet. (%.2f secs buffered)",
-              durationUs / 1E6);
-        return false;
-    }
-
-    return true;
-}
-
-void NuPlayer2::StreamingSource::setError(status_t err) {
-    Mutex::Autolock _l(mBufferingLock);
-    mFinalResult = err;
-}
-
-sp<AnotherPacketSource> NuPlayer2::StreamingSource::getSource(bool audio) {
-    if (mTSParser == NULL) {
-        return NULL;
-    }
-
-    sp<MediaSource> source = mTSParser->getSource(
-            audio ? ATSParser::AUDIO : ATSParser::VIDEO);
-
-    return static_cast<AnotherPacketSource *>(source.get());
-}
-
-sp<AMessage> NuPlayer2::StreamingSource::getFormat(bool audio) {
-    sp<AnotherPacketSource> source = getSource(audio);
-
-    sp<AMessage> format = new AMessage;
-    if (source == NULL) {
-        format->setInt32("err", -EWOULDBLOCK);
-        return format;
-    }
-
-    sp<MetaData> meta = source->getFormat();
-    if (meta == NULL) {
-        format->setInt32("err", -EWOULDBLOCK);
-        return format;
-    }
-    status_t err = convertMetaDataToMessage(meta, &format);
-    if (err != OK) { // format may have been cleared on error
-        return NULL;
-    }
-    return format;
-}
-
-status_t NuPlayer2::StreamingSource::dequeueAccessUnit(
-        bool audio, sp<ABuffer> *accessUnit) {
-    sp<AnotherPacketSource> source = getSource(audio);
-
-    if (source == NULL) {
-        return -EWOULDBLOCK;
-    }
-
-    if (!haveSufficientDataOnAllTracks()) {
-        postReadBuffer();
-    }
-
-    status_t finalResult;
-    if (!source->hasBufferAvailable(&finalResult)) {
-        return finalResult == OK ? -EWOULDBLOCK : finalResult;
-    }
-
-    status_t err = source->dequeueAccessUnit(accessUnit);
-
-#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0
-    if (err == OK) {
-        int64_t timeUs;
-        CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
-        ALOGV("dequeueAccessUnit timeUs=%lld us", timeUs);
-    }
-#endif
-
-    return err;
-}
-
-bool NuPlayer2::StreamingSource::isRealTime() const {
-    return mSource->flags() & IStreamSource::kFlagIsRealTimeData;
-}
-
-void NuPlayer2::StreamingSource::onMessageReceived(
-        const sp<AMessage> &msg) {
-    switch (msg->what()) {
-        case kWhatReadBuffer:
-        {
-            onReadBuffer();
-
-            {
-                Mutex::Autolock _l(mBufferingLock);
-                mBuffering = false;
-            }
-            break;
-        }
-        default:
-        {
-            TRESPASS();
-        }
-    }
-}
-
-
-}  // namespace android
-
diff --git a/media/libmedia/nuplayer2/StreamingSource.h b/media/libmedia/nuplayer2/StreamingSource.h
deleted file mode 100644
index 4b89c38..0000000
--- a/media/libmedia/nuplayer2/StreamingSource.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2010 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 STREAMING_SOURCE_H_
-
-#define STREAMING_SOURCE_H_
-
-#include "NuPlayer2.h"
-#include "NuPlayer2Source.h"
-
-namespace android {
-
-struct ABuffer;
-struct ATSParser;
-struct AnotherPacketSource;
-
-struct NuPlayer2::StreamingSource : public NuPlayer2::Source {
-    StreamingSource(
-            const sp<AMessage> &notify,
-            const sp<IStreamSource> &source);
-
-    virtual status_t getBufferingSettings(
-            BufferingSettings* buffering /* nonnull */) override;
-    virtual status_t setBufferingSettings(const BufferingSettings& buffering) override;
-
-    virtual void prepareAsync();
-    virtual void start();
-
-    virtual status_t feedMoreTSData();
-
-    virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
-
-    virtual bool isRealTime() const;
-
-protected:
-    virtual ~StreamingSource();
-
-    virtual void onMessageReceived(const sp<AMessage> &msg);
-
-    virtual sp<AMessage> getFormat(bool audio);
-
-private:
-    enum {
-        kWhatReadBuffer,
-    };
-    sp<IStreamSource> mSource;
-    status_t mFinalResult;
-    sp<StreamListener> mStreamListener;
-    sp<ATSParser> mTSParser;
-
-    bool mBuffering;
-    Mutex mBufferingLock;
-    sp<ALooper> mLooper;
-
-    void setError(status_t err);
-    sp<AnotherPacketSource> getSource(bool audio);
-    bool haveSufficientDataOnAllTracks();
-    status_t postReadBuffer();
-    void onReadBuffer();
-
-    DISALLOW_EVIL_CONSTRUCTORS(StreamingSource);
-};
-
-}  // namespace android
-
-#endif  // STREAMING_SOURCE_H_
diff --git a/media/libmediaextractor/include/media/MediaExtractor.h b/media/libmediaextractor/include/media/MediaExtractor.h
index 60495ec..73c5f10 100644
--- a/media/libmediaextractor/include/media/MediaExtractor.h
+++ b/media/libmediaextractor/include/media/MediaExtractor.h
@@ -32,7 +32,6 @@
 class String8;
 struct AMessage;
 struct MediaSourceBase;
-typedef std::vector<uint8_t> HInterfaceToken;
 
 
 class ExtractorAllocTracker {
@@ -81,7 +80,7 @@
     }
     virtual void setUID(uid_t /*uid*/) {
     }
-    virtual status_t setMediaCas(const HInterfaceToken &/*casToken*/) {
+    virtual status_t setMediaCas(const uint8_t* /*casToken*/, size_t /*size*/) {
         return INVALID_OPERATION;
     }
 
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index 601c9fa..d190780 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -127,7 +127,7 @@
 }
 
 status_t RemoteMediaExtractor::setMediaCas(const HInterfaceToken &casToken) {
-    return mExtractor->setMediaCas(casToken);
+    return mExtractor->setMediaCas((uint8_t*)casToken.data(), casToken.size());
 }
 
 const char * RemoteMediaExtractor::name() {
diff --git a/packages/MediaComponents/res/values/themes.xml b/packages/MediaComponents/res/values/themes.xml
index 51098e9..d9a754b 100644
--- a/packages/MediaComponents/res/values/themes.xml
+++ b/packages/MediaComponents/res/values/themes.xml
@@ -16,8 +16,8 @@
 
 <resources>
 
-    <style name="Theme.MediaRouter" parent="ThemeOverlay.AppCompat.Dark">
-        <item name="windowNoTitle">true</item>
+    <style name="Theme.MediaRouter" parent="android:Theme.Material">
+        <item name="android:windowNoTitle">true</item>
         <item name="mediaRouteButtonStyle">@style/Widget.MediaRouter.MediaRouteButton</item>
 
         <item name="mediaRouteCloseDrawable">@drawable/mr_dialog_close_dark</item>
@@ -37,8 +37,8 @@
         <item name="mediaRouteControlPanelThemeOverlay">@style/ThemeOverlay.MediaRouter.Light</item>
     </style>
 
-    <style name="Theme.MediaRouter.Light" parent="ThemeOverlay.AppCompat.Light">
-        <item name="windowNoTitle">true</item>
+    <style name="Theme.MediaRouter.Light" parent="android:Theme.Material.Light">
+        <item name="android:windowNoTitle">true</item>
         <item name="mediaRouteButtonStyle">@style/Widget.MediaRouter.Light.MediaRouteButton</item>
 
         <item name="mediaRouteCloseDrawable">@drawable/mr_dialog_close_light</item>
@@ -58,14 +58,14 @@
         <item name="mediaRouteControlPanelThemeOverlay">@style/ThemeOverlay.MediaRouter.Dark</item>
     </style>
 
-    <style name="ThemeOverlay.MediaRouter.Dark" parent="ThemeOverlay.AppCompat.Dark">
+    <style name="ThemeOverlay.MediaRouter.Dark" parent="android:Theme.Material">
         <item name="mediaRoutePlayDrawable">@drawable/mr_media_play_dark</item>
         <item name="mediaRoutePauseDrawable">@drawable/mr_media_pause_dark</item>
         <item name="mediaRouteStopDrawable">@drawable/mr_media_stop_dark</item>
         <item name="mediaRouteAudioTrackDrawable">@drawable/mr_vol_type_audiotrack_dark</item>
 
     </style>
-    <style name="ThemeOverlay.MediaRouter.Light" parent="ThemeOverlay.AppCompat.Light">
+    <style name="ThemeOverlay.MediaRouter.Light" parent="android:Theme.Material.Light">
         <item name="mediaRoutePlayDrawable">@drawable/mr_media_play_light</item>
         <item name="mediaRoutePauseDrawable">@drawable/mr_media_pause_light</item>
         <item name="mediaRouteStopDrawable">@drawable/mr_media_stop_light</item>
diff --git a/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl b/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl
index d5bd354..7702bda 100644
--- a/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl
+++ b/packages/MediaComponents/src/com/android/media/IMediaSession2.aidl
@@ -18,6 +18,7 @@
 
 import android.os.Bundle;
 import android.os.ResultReceiver;
+import android.net.Uri;
 
 import com.android.media.IMediaSession2Callback;
 
@@ -27,8 +28,7 @@
  * Keep this interface oneway. Otherwise a malicious app may implement fake version of this,
  * and holds calls from session to make session owner(s) frozen.
  */
-// TODO: Consider to make some methods oneway
-interface IMediaSession2 {
+oneway interface IMediaSession2 {
     // TODO(jaewan): add onCommand() to send private command
     // TODO(jaewan): Due to the nature of oneway calls, APIs can be called in out of order
     //               Add id for individual calls to address this.
@@ -40,6 +40,9 @@
     void connect(String callingPackage, IMediaSession2Callback callback);
     void release(IMediaSession2Callback caller);
 
+    void setVolumeTo(IMediaSession2Callback caller, int value, int flags);
+    void adjustVolume(IMediaSession2Callback caller, int direction, int flags);
+
     //////////////////////////////////////////////////////////////////////////////////////////////
     // send command
     //////////////////////////////////////////////////////////////////////////////////////////////
@@ -49,7 +52,14 @@
     void sendCustomCommand(IMediaSession2Callback caller, in Bundle command, in Bundle args,
             in ResultReceiver receiver);
 
-    //////////////////////////////////////////////////////////////////////////////////////////////
+    void prepareFromUri(IMediaSession2Callback caller, in Uri uri, in Bundle extra);
+    void prepareFromSearch(IMediaSession2Callback caller, String query, in Bundle extra);
+    void prepareFromMediaId(IMediaSession2Callback caller, String mediaId, in Bundle extra);
+    void playFromUri(IMediaSession2Callback caller, in Uri uri, in Bundle extra);
+    void playFromSearch(IMediaSession2Callback caller, String query, in Bundle extra);
+    void playFromMediaId(IMediaSession2Callback caller, String mediaId, in Bundle extra);
+
+   //////////////////////////////////////////////////////////////////////////////////////////////
     // Get library service specific
     //////////////////////////////////////////////////////////////////////////////////////////////
     void getBrowserRoot(IMediaSession2Callback callback, in Bundle rootHints);
diff --git a/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl b/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
index eaf404c..a443bf8 100644
--- a/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
+++ b/packages/MediaComponents/src/com/android/media/IMediaSession2Callback.aidl
@@ -16,6 +16,7 @@
 
 package com.android.media;
 
+import android.app.PendingIntent;
 import android.os.Bundle;
 import android.os.ResultReceiver;
 
@@ -33,19 +34,11 @@
     void onPlaylistParamsChanged(in Bundle params);
     void onPlaybackInfoChanged(in Bundle playbackInfo);
 
-    /**
-     * Called only when the controller is created with service's token.
-     *
-     * @param sessionBinder {@code null} if the connect is rejected or is disconnected. a session
-     *     binder if the connect is accepted.
-     * @param commands initially allowed commands.
-     */
-    // TODO(jaewan): Also need to pass flags for allowed actions for permission check.
-    //               For example, a media can allow setRating only for whitelisted apps
-    //               it's better for controller to know such information in advance.
-    //               Follow-up TODO: Add similar functions to the session.
-    // TODO(jaewan): Is term 'accepted/rejected' correct? For permission, 'grant' is used.
-    void onConnectionChanged(IMediaSession2 sessionBinder, in Bundle commandGroup);
+    // TODO(jaewan): Handle when the playlist becomes too huge.
+    void onConnected(IMediaSession2 sessionBinder, in Bundle commandGroup, in Bundle playbackState,
+            in Bundle playbackInfo, in Bundle params, in List<Bundle> playlist, int ratingType,
+            in PendingIntent sessionActivity);
+    void onDisconnected();
 
     void onCustomLayoutChanged(in List<Bundle> commandButtonlist);
 
diff --git a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
index 6ee79a0..a477d1d 100644
--- a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
@@ -76,6 +76,12 @@
     private PlaylistParams mPlaylistParams;
     @GuardedBy("mLock")
     private PlaybackInfo mPlaybackInfo;
+    @GuardedBy("mLock")
+    private int mRatingType;
+    @GuardedBy("mLock")
+    private PendingIntent mSessionActivity;
+    @GuardedBy("mLock")
+    private CommandGroup mCommandGroup;
 
     // Assignment should be used with the lock hold, but should be used without a lock to prevent
     // potential deadlock.
@@ -274,56 +280,127 @@
     //////////////////////////////////////////////////////////////////////////////////////
     @Override
     public PendingIntent getSessionActivity_impl() {
-        // TODO(jaewan): Implement
-        return null;
+        return mSessionActivity;
     }
 
     @Override
     public int getRatingType_impl() {
-        // TODO(jaewan): Implement
-        return 0;
+        return mRatingType;
     }
 
     @Override
     public void setVolumeTo_impl(int value, int flags) {
-        // TODO(jaewan): Implement
+        // TODO(hdmoon): sanity check
+        final IMediaSession2 binder = mSessionBinder;
+        if (binder != null) {
+            try {
+                binder.setVolumeTo(mSessionCallbackStub, value, flags);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+            }
+        } else {
+            Log.w(TAG, "Session isn't active", new IllegalStateException());
+        }
     }
 
     @Override
     public void adjustVolume_impl(int direction, int flags) {
-        // TODO(jaewan): Implement
+        // TODO(hdmoon): sanity check
+        final IMediaSession2 binder = mSessionBinder;
+        if (binder != null) {
+            try {
+                binder.adjustVolume(mSessionCallbackStub, direction, flags);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+            }
+        } else {
+            Log.w(TAG, "Session isn't active", new IllegalStateException());
+        }
     }
 
     @Override
     public void prepareFromUri_impl(Uri uri, Bundle extras) {
-        // TODO(jaewan): Implement
+        final IMediaSession2 binder = mSessionBinder;
+        if (binder != null) {
+            try {
+                binder.prepareFromUri(mSessionCallbackStub, uri, extras);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+            }
+        } else {
+            // TODO(jaewan): Handle.
+        }
     }
 
     @Override
     public void prepareFromSearch_impl(String query, Bundle extras) {
-        // TODO(jaewan): Implement
+        final IMediaSession2 binder = mSessionBinder;
+        if (binder != null) {
+            try {
+                binder.prepareFromSearch(mSessionCallbackStub, query, extras);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+            }
+        } else {
+            // TODO(jaewan): Handle.
+        }
     }
 
     @Override
     public void prepareMediaId_impl(String mediaId, Bundle extras) {
-        // TODO(jaewan): Implement
+        final IMediaSession2 binder = mSessionBinder;
+        if (binder != null) {
+            try {
+                binder.prepareFromMediaId(mSessionCallbackStub, mediaId, extras);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+            }
+        } else {
+            // TODO(jaewan): Handle.
+        }
+    }
+
+    @Override
+    public void playFromUri_impl(Uri uri, Bundle extras) {
+        final IMediaSession2 binder = mSessionBinder;
+        if (binder != null) {
+            try {
+                binder.playFromUri(mSessionCallbackStub, uri, extras);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+            }
+        } else {
+            // TODO(jaewan): Handle.
+        }
     }
 
     @Override
     public void playFromSearch_impl(String query, Bundle extras) {
-        // TODO(jaewan): Implement
-    }
-
-    @Override
-    public void playFromUri_impl(String uri, Bundle extras) {
-        // TODO(jaewan): Implement
+        final IMediaSession2 binder = mSessionBinder;
+        if (binder != null) {
+            try {
+                binder.playFromSearch(mSessionCallbackStub, query, extras);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+            }
+        } else {
+            // TODO(jaewan): Handle.
+        }
     }
 
     @Override
     public void playFromMediaId_impl(String mediaId, Bundle extras) {
-        // TODO(jaewan): Implement
+        final IMediaSession2 binder = mSessionBinder;
+        if (binder != null) {
+            try {
+                binder.playFromMediaId(mSessionCallbackStub, mediaId, extras);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Cannot connect to the service or the session is gone", e);
+            }
+        } else {
+            // TODO(jaewan): Handle.
+        }
     }
-
     @Override
     public void setRating_impl(Rating2 rating) {
         // TODO(jaewan): Implement
@@ -484,19 +561,20 @@
         }
     }
 
-    // Called when the result for connecting to the session was delivered.
     // Should be used without a lock to prevent potential deadlock.
-    private void onConnectionChangedNotLocked(IMediaSession2 sessionBinder,
-            CommandGroup commandGroup) {
+    private void onConnectedNotLocked(IMediaSession2 sessionBinder,
+            final CommandGroup commandGroup, final PlaybackState2 state, final PlaybackInfo info,
+            final PlaylistParams params, final List<MediaItem2> playlist, final int ratingType,
+            final PendingIntent sessionActivity) {
         if (DEBUG) {
-            Log.d(TAG, "onConnectionChangedNotLocked sessionBinder=" + sessionBinder
+            Log.d(TAG, "onConnectedNotLocked sessionBinder=" + sessionBinder
                     + ", commands=" + commandGroup);
         }
-        boolean release = false;
+        boolean close = false;
         try {
             if (sessionBinder == null || commandGroup == null) {
                 // Connection rejected.
-                release = true;
+                close = true;
                 return;
             }
             synchronized (mLock) {
@@ -506,9 +584,16 @@
                 if (mSessionBinder != null) {
                     Log.e(TAG, "Cannot be notified about the connection result many times."
                             + " Probably a bug or malicious app.");
-                    release = true;
+                    close = true;
                     return;
                 }
+                mCommandGroup = commandGroup;
+                mPlaybackState = state;
+                mPlaybackInfo = info;
+                mPlaylistParams = params;
+                mPlaylist = playlist;
+                mRatingType = ratingType;
+                mSessionActivity = sessionActivity;
                 mSessionBinder = sessionBinder;
                 try {
                     // Implementation for the local binder is no-op,
@@ -518,16 +603,19 @@
                     if (DEBUG) {
                         Log.d(TAG, "Session died too early.", e);
                     }
-                    release = true;
+                    close = true;
                     return;
                 }
             }
             // TODO(jaewan): Keep commands to prevents illegal API calls.
             mCallbackExecutor.execute(() -> {
+                // Note: We may trigger ControllerCallbacks with the initial values
+                // But it's hard to define the order of the controller callbacks
+                // Only notify about the
                 mCallback.onConnected(commandGroup);
             });
         } finally {
-            if (release) {
+            if (close) {
                 // Trick to call release() without holding the lock, to prevent potential deadlock
                 // with the developer's custom lock within the ControllerCallback.onDisconnected().
                 mInstance.close();
@@ -619,6 +707,9 @@
 
         @Override
         public void onPlaybackInfoChanged(Bundle playbackInfo) throws RuntimeException {
+            if (DEBUG) {
+                Log.d(TAG, "onPlaybackInfoChanged");
+            }
             final MediaController2Impl controller;
             try {
                 controller = getController();
@@ -631,17 +722,42 @@
         }
 
         @Override
-        public void onConnectionChanged(IMediaSession2 sessionBinder, Bundle commandGroup)
-                throws RuntimeException {
-            final MediaController2Impl controller;
-            try {
-                controller = getController();
-            } catch (IllegalStateException e) {
-                Log.w(TAG, "Don't fail silently here. Highly likely a bug");
+        public void onConnected(IMediaSession2 sessionBinder, Bundle commandGroup,
+                Bundle playbackState, Bundle playbackInfo, Bundle playlistParams, List<Bundle>
+                playlist, int ratingType, PendingIntent sessionActivity) {
+            final MediaController2Impl controller = mController.get();
+            if (controller == null) {
+                if (DEBUG) {
+                    Log.d(TAG, "onConnected after MediaController2.close()");
+                }
                 return;
             }
-            controller.onConnectionChangedNotLocked(
-                    sessionBinder, CommandGroup.fromBundle(controller.getContext(), commandGroup));
+            final Context context = controller.getContext();
+            List<MediaItem2> list = new ArrayList<>();
+            for (int i = 0; i < playlist.size(); i++) {
+                MediaItem2 item = MediaItem2.fromBundle(context, playlist.get(i));
+                if (item != null) {
+                    list.add(item);
+                }
+            }
+            controller.onConnectedNotLocked(sessionBinder,
+                    CommandGroup.fromBundle(context, commandGroup),
+                    PlaybackState2.fromBundle(context, playbackState),
+                    PlaybackInfoImpl.fromBundle(context, playbackInfo),
+                    PlaylistParams.fromBundle(context, playlistParams),
+                    list, ratingType, sessionActivity);
+        }
+
+        @Override
+        public void onDisconnected() {
+            final MediaController2Impl controller = mController.get();
+            if (controller == null) {
+                if (DEBUG) {
+                    Log.d(TAG, "onDisconnected after MediaController2.close()");
+                }
+                return;
+            }
+            controller.mInstance.close();
         }
 
         @Override
@@ -667,6 +783,7 @@
                 // Illegal call. Ignore
                 return;
             }
+            // TODO(jaewan): Fix here. It's controller feature so shouldn't use browser
             final MediaBrowser2Impl browser;
             try {
                 browser = getBrowser();
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
index cde98d2..f323a17 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
@@ -85,6 +85,8 @@
     private final SessionToken2 mSessionToken;
     private final AudioManager mAudioManager;
     private final List<PlaybackListenerHolder> mListeners = new ArrayList<>();
+    private final int mRatingType;
+    private final PendingIntent mSessionActivity;
 
     @GuardedBy("mLock")
     private MediaPlayerInterface mPlayer;
@@ -102,7 +104,6 @@
     /**
      * Can be only called by the {@link Builder#build()}.
      *
-     * @param instance
      * @param context
      * @param player
      * @param id
@@ -123,6 +124,8 @@
         mId = id;
         mCallback = callback;
         mCallbackExecutor = callbackExecutor;
+        mRatingType = ratingType;
+        mSessionActivity = sessionActivity;
         mSessionStub = new MediaSession2Stub(this);
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
 
@@ -195,9 +198,6 @@
         if (player == null) {
             throw new IllegalArgumentException("player shouldn't be null");
         }
-        if (player == mPlayer) {
-            return;
-        }
         PlaybackInfo info =
                 createPlaybackInfo(null /* VolumeProvider */, player.getAudioAttributes());
         synchronized (mLock) {
@@ -218,10 +218,6 @@
         if (volumeProvider == null) {
             throw new IllegalArgumentException("volumeProvider shouldn't be null");
         }
-        if (player == mPlayer) {
-            return;
-        }
-
         PlaybackInfo info = createPlaybackInfo(volumeProvider, player.getAudioAttributes());
         synchronized (mLock) {
             setPlayerLocked(player);
@@ -244,12 +240,25 @@
     private PlaybackInfo createPlaybackInfo(VolumeProvider2 volumeProvider, AudioAttributes attrs) {
         PlaybackInfo info;
         if (volumeProvider == null) {
-            int stream = attrs == null ? AudioManager.STREAM_MUSIC : attrs.getVolumeControlStream();
+            int stream;
+            if (attrs == null) {
+                stream = AudioManager.STREAM_MUSIC;
+            } else {
+                stream = attrs.getVolumeControlStream();
+                if (stream == AudioManager.USE_DEFAULT_STREAM_TYPE) {
+                    // It may happen if the AudioAttributes doesn't have usage.
+                    // Change it to the STREAM_MUSIC because it's not supported by audio manager
+                    // for querying volume level.
+                    stream = AudioManager.STREAM_MUSIC;
+                }
+            }
             info = PlaybackInfoImpl.createPlaybackInfo(
                     mContext,
                     PlaybackInfo.PLAYBACK_TYPE_LOCAL,
                     attrs,
-                    VolumeProvider2.VOLUME_CONTROL_ABSOLUTE,
+                    mAudioManager.isVolumeFixed()
+                            ? VolumeProvider2.VOLUME_CONTROL_FIXED
+                            : VolumeProvider2.VOLUME_CONTROL_ABSOLUTE,
                     mAudioManager.getStreamMaxVolume(stream),
                     mAudioManager.getStreamVolume(stream));
         } else {
@@ -559,6 +568,24 @@
         return mCallback;
     }
 
+    VolumeProvider2 getVolumeProvider() {
+        return mVolumeProvider;
+    }
+
+    PlaybackInfo getPlaybackInfo() {
+        synchronized (mLock) {
+            return mPlaybackInfo;
+        }
+    }
+
+    int getRatingType() {
+        return mRatingType;
+    }
+
+    PendingIntent getSessionActivity() {
+        return mSessionActivity;
+    }
+
     private static class MyPlaybackListener implements MediaPlayerInterface.PlaybackListener {
         private final WeakReference<MediaSession2Impl> mSession;
         private final MediaPlayerInterface mPlayer;
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
index 5d3a06e..2380fc0 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
@@ -16,8 +16,10 @@
 
 package com.android.media;
 
+import android.app.PendingIntent;
 import android.content.Context;
 import android.media.MediaController2;
+import android.media.MediaController2.PlaybackInfo;
 import android.media.MediaItem2;
 import android.media.MediaLibraryService2.LibraryRoot;
 import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
@@ -28,7 +30,9 @@
 import android.media.MediaSession2.ControllerInfo;
 import android.media.MediaSession2.PlaylistParams;
 import android.media.PlaybackState2;
+import android.media.VolumeProvider2;
 import android.media.update.MediaSession2Provider.CommandButtonProvider;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -77,7 +81,7 @@
                     ((ControllerInfoImpl) list.get(i).getProvider()).getControllerBinder();
             try {
                 // Should be used without a lock hold to prevent potential deadlock.
-                callbackBinder.onConnectionChanged(null, null);
+                callbackBinder.onDisconnected();
             } catch (RemoteException e) {
                 // Controller is gone. Should be fine because we're destroying.
             }
@@ -110,7 +114,11 @@
             // media keys to.
             boolean accept = allowedCommands != null || request.isTrusted();
             ControllerInfoImpl impl = ControllerInfoImpl.from(request);
-            if (accept) {
+            if (accept && allowedCommands != null) {
+                if (DEBUG) {
+                    Log.d(TAG, "Accepting connection, request=" + request
+                            + " allowedCommands=" + allowedCommands);
+                }
                 synchronized (mLock) {
                     mControllers.put(impl.getId(), request);
                 }
@@ -118,20 +126,6 @@
                     // For trusted apps, send non-null allowed commands to keep connection.
                     allowedCommands = new CommandGroup(context);
                 }
-            }
-            if (DEBUG) {
-                Log.d(TAG, "onConnectResult, request=" + request
-                        + " accept=" + accept);
-            }
-            try {
-                callback.onConnectionChanged(
-                        accept ? MediaSession2Stub.this : null,
-                        allowedCommands == null ? null : allowedCommands.toBundle());
-            } catch (RemoteException e) {
-                // Controller may be died prematurely.
-            }
-            if (accept) {
-                // TODO(jaewan): We need to send current PlaybackInfo.
                 // If connection is accepted, notify the current state to the controller.
                 // It's needed because we cannot call synchronous calls between session/controller.
                 // Note: We're doing this after the onConnectionChanged(), but there's no guarantee
@@ -140,12 +134,50 @@
                 //       use thread poll for incoming calls.
                 // TODO(jaewan): Should we protect getting playback state?
                 final PlaybackState2 state = session.getInstance().getPlaybackState();
-                final Bundle bundle = state != null ? state.toBundle() : null;
+                final Bundle playbackStateBundle = (state != null) ? state.toBundle() : null;
+                final Bundle playbackInfoBundle =
+                        ((PlaybackInfoImpl) session.getPlaybackInfo().getProvider()).toBundle();
+                final PlaylistParams params = session.getInstance().getPlaylistParams();
+                final Bundle paramsBundle = (params != null) ? params.toBundle() : null;
+                final int ratingType = session.getRatingType();
+                final PendingIntent sessionActivity = session.getSessionActivity();
+                final List<MediaItem2> playlist = session.getInstance().getPlaylist();
+                final List<Bundle> playlistBundle = new ArrayList<>();
+                if (playlist != null) {
+                    // TODO(jaewan): Find a way to avoid concurrent modification exception.
+                    for (int i = 0; i < playlist.size(); i++) {
+                        final MediaItem2 item = playlist.get(i);
+                        if (item != null) {
+                            final Bundle itemBundle = item.toBundle();
+                            if (itemBundle != null) {
+                                playlistBundle.add(itemBundle);
+                            }
+                        }
+                    }
+                }
+
+                // Double check if session is still there, because close() can be called in another
+                // thread.
+                if (mSession.get() == null) {
+                    return;
+                }
                 try {
-                    callback.onPlaybackStateChanged(bundle);
+                    callback.onConnected(MediaSession2Stub.this,
+                            allowedCommands.toBundle(), playbackStateBundle, playbackInfoBundle,
+                            paramsBundle, playlistBundle, ratingType, sessionActivity);
                 } catch (RemoteException e) {
-                    // TODO(jaewan): Handle this.
                     // Controller may be died prematurely.
+                    // TODO(jaewan): Handle here.
+                }
+            } else {
+                if (DEBUG) {
+                    Log.d(TAG, "Rejecting connection, request=" + request);
+                }
+                try {
+                    callback.onDisconnected();
+                } catch (RemoteException e) {
+                    // Controller may be died prematurely.
+                    // Not an issue because we'll ignore it anyway.
                 }
             }
         });
@@ -162,6 +194,82 @@
     }
 
     @Override
+    public void setVolumeTo(IMediaSession2Callback caller, int value, int flags)
+            throws RuntimeException {
+        final MediaSession2Impl sessionImpl = getSession();
+        final ControllerInfo controller = getController(caller);
+        if (controller == null) {
+            if (DEBUG) {
+                Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+            }
+            return;
+        }
+        sessionImpl.getCallbackExecutor().execute(() -> {
+            final MediaSession2Impl session = mSession.get();
+            if (session == null) {
+                return;
+            }
+            // TODO(jaewan): Sanity check.
+            Command command = new Command(
+                    session.getContext(), MediaSession2.COMMAND_CODE_SET_VOLUME);
+            boolean accepted = session.getCallback().onCommandRequest(controller, command);
+            if (!accepted) {
+                // Don't run rejected command.
+                if (DEBUG) {
+                    Log.d(TAG, "Command " + MediaSession2.COMMAND_CODE_SET_VOLUME + " from "
+                            + controller + " was rejected by " + session);
+                }
+                return;
+            }
+
+            VolumeProvider2 volumeProvider = session.getVolumeProvider();
+            if (volumeProvider == null) {
+                // TODO(jaewan): Set local stream volume
+            } else {
+                volumeProvider.onSetVolumeTo(value);
+            }
+        });
+    }
+
+    @Override
+    public void adjustVolume(IMediaSession2Callback caller, int direction, int flags)
+            throws RuntimeException {
+        final MediaSession2Impl sessionImpl = getSession();
+        final ControllerInfo controller = getController(caller);
+        if (controller == null) {
+            if (DEBUG) {
+                Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+            }
+            return;
+        }
+        sessionImpl.getCallbackExecutor().execute(() -> {
+            final MediaSession2Impl session = mSession.get();
+            if (session == null) {
+                return;
+            }
+            // TODO(jaewan): Sanity check.
+            Command command = new Command(
+                    session.getContext(), MediaSession2.COMMAND_CODE_SET_VOLUME);
+            boolean accepted = session.getCallback().onCommandRequest(controller, command);
+            if (!accepted) {
+                // Don't run rejected command.
+                if (DEBUG) {
+                    Log.d(TAG, "Command " + MediaSession2.COMMAND_CODE_SET_VOLUME + " from "
+                            + controller + " was rejected by " + session);
+                }
+                return;
+            }
+
+            VolumeProvider2 volumeProvider = session.getVolumeProvider();
+            if (volumeProvider == null) {
+                // TODO(jaewan): Adjust local stream volume
+            } else {
+                volumeProvider.onAdjustVolume(direction);
+            }
+        });
+    }
+
+    @Override
     public void sendCommand(IMediaSession2Callback caller, Bundle command, Bundle args)
             throws RuntimeException {
         // TODO(jaewan): Generic command
@@ -260,6 +368,126 @@
     }
 
     @Override
+    public void prepareFromUri(final IMediaSession2Callback caller, final Uri uri,
+            final Bundle extra) {
+        final MediaSession2Impl sessionImpl = getSession();
+        final ControllerInfo controller = getController(caller);
+        if (controller == null) {
+            if (DEBUG) {
+                Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+            }
+            return;
+        }
+        sessionImpl.getCallbackExecutor().execute(() -> {
+            final MediaSession2Impl session = mSession.get();
+            if (session == null) {
+                return;
+            }
+            session.getCallback().onPrepareFromUri(controller, uri, extra);
+        });
+    }
+
+    @Override
+    public void prepareFromSearch(final IMediaSession2Callback caller, final String query,
+            final Bundle extra) {
+        final MediaSession2Impl sessionImpl = getSession();
+        final ControllerInfo controller = getController(caller);
+        if (controller == null) {
+            if (DEBUG) {
+                Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+            }
+            return;
+        }
+        sessionImpl.getCallbackExecutor().execute(() -> {
+            final MediaSession2Impl session = mSession.get();
+            if (session == null) {
+                return;
+            }
+            session.getCallback().onPrepareFromSearch(controller, query, extra);
+        });
+    }
+
+    @Override
+    public void prepareFromMediaId(final IMediaSession2Callback caller, final String mediaId,
+            final Bundle extra) {
+        final MediaSession2Impl sessionImpl = getSession();
+        final ControllerInfo controller = getController(caller);
+        if (controller == null) {
+            if (DEBUG) {
+                Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+            }
+            return;
+        }
+        sessionImpl.getCallbackExecutor().execute(() -> {
+            final MediaSession2Impl session = mSession.get();
+            if (session == null) {
+                return;
+            }
+            session.getCallback().onPrepareFromMediaId(controller, mediaId, extra);
+        });
+    }
+
+    @Override
+    public void playFromUri(final IMediaSession2Callback caller, final Uri uri,
+            final Bundle extra) {
+        final MediaSession2Impl sessionImpl = getSession();
+        final ControllerInfo controller = getController(caller);
+        if (controller == null) {
+            if (DEBUG) {
+                Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+            }
+            return;
+        }
+        sessionImpl.getCallbackExecutor().execute(() -> {
+            final MediaSession2Impl session = mSession.get();
+            if (session == null) {
+                return;
+            }
+            session.getCallback().onPlayFromUri(controller, uri, extra);
+        });
+    }
+
+    @Override
+    public void playFromSearch(final IMediaSession2Callback caller, final String query,
+            final Bundle extra) {
+        final MediaSession2Impl sessionImpl = getSession();
+        final ControllerInfo controller = getController(caller);
+        if (controller == null) {
+            if (DEBUG) {
+                Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+            }
+            return;
+        }
+        sessionImpl.getCallbackExecutor().execute(() -> {
+            final MediaSession2Impl session = mSession.get();
+            if (session == null) {
+                return;
+            }
+            session.getCallback().onPlayFromSearch(controller, query, extra);
+        });
+    }
+
+    @Override
+    public void playFromMediaId(final IMediaSession2Callback caller, final String mediaId,
+            final Bundle extra) {
+        final MediaSession2Impl sessionImpl = getSession();
+        final ControllerInfo controller = getController(caller);
+        if (controller == null) {
+            if (DEBUG) {
+                Log.d(TAG, "Command from a controller that hasn't connected. Ignore");
+            }
+            return;
+        }
+        sessionImpl.getCallbackExecutor().execute(() -> {
+            final MediaSession2Impl session = mSession.get();
+            if (session == null) {
+                return;
+            }
+            session.getCallback().onPlayFromMediaId(controller, mediaId, extra);
+        });
+    }
+
+    @Override
     public void getBrowserRoot(IMediaSession2Callback caller, Bundle rootHints)
             throws RuntimeException {
         final MediaSession2Impl sessionImpl = getSession();
diff --git a/packages/MediaComponents/src/com/android/media/update/ApiHelper.java b/packages/MediaComponents/src/com/android/media/update/ApiHelper.java
index b0ca1bd..06f463f 100644
--- a/packages/MediaComponents/src/com/android/media/update/ApiHelper.java
+++ b/packages/MediaComponents/src/com/android/media/update/ApiHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.media.update;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -24,6 +25,7 @@
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.ViewGroup;
 
 import com.android.support.mediarouter.app.MediaRouteButton;
 
@@ -51,13 +53,23 @@
         return sInstance.mLibResources;
     }
 
-    public static Resources.Theme getLibTheme() {
+    public static Theme getLibTheme() {
         return sInstance.mLibTheme;
     }
 
+    public static Theme getLibTheme(int themeId) {
+        Theme theme = sInstance.mLibResources.newTheme();
+        theme.applyStyle(themeId, true);
+        return theme;
+    }
+
     public static LayoutInflater getLayoutInflater(Context context) {
+        return getLayoutInflater(context, getLibTheme());
+    }
+
+    public static LayoutInflater getLayoutInflater(Context context, Theme theme) {
         LayoutInflater layoutInflater = LayoutInflater.from(context).cloneInContext(
-                new ContextThemeWrapper(context, getLibTheme()));
+                new ContextThemeWrapper(context, theme));
         layoutInflater.setFactory2(new LayoutInflater.Factory2() {
             @Override
             public View onCreateView(
@@ -77,8 +89,17 @@
     }
 
     public static View inflateLibLayout(Context context, int libResId) {
+        return inflateLibLayout(context, getLibTheme(), libResId, null, false);
+    }
+
+    public static View inflateLibLayout(Context context, Theme theme, int libResId) {
+        return inflateLibLayout(context, theme, libResId, null, false);
+    }
+
+    public static View inflateLibLayout(Context context, Theme theme, int libResId,
+            @Nullable ViewGroup root, boolean attachToRoot) {
         try (XmlResourceParser parser = getLibResources().getLayout(libResId)) {
-            return getLayoutInflater(context).inflate(parser, null);
+            return getLayoutInflater(context, theme).inflate(parser, root, attachToRoot);
         }
     }
 }
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java
index 7fdcfe4..fa94a81 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteButton.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.app.Activity;
+import android.app.FragmentManager;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.res.ColorStateList;
@@ -27,8 +28,6 @@
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.app.FragmentManager;
 import android.support.v4.graphics.drawable.DrawableCompat;
 import android.support.v7.widget.TooltipCompat;
 import android.util.AttributeSet;
@@ -259,7 +258,7 @@
             return false;
         }
 
-        final FragmentManager fm = getFragmentManager();
+        final FragmentManager fm = getActivity().getFragmentManager();
         if (fm == null) {
             throw new IllegalStateException("The activity must be a subclass of FragmentActivity");
         }
@@ -286,13 +285,6 @@
         return true;
     }
 
-    private FragmentManager getFragmentManager() {
-        Activity activity = getActivity();
-        if (activity instanceof FragmentActivity) {
-            return ((FragmentActivity)activity).getSupportFragmentManager();
-        }
-        return null;
-    }
 
     private Activity getActivity() {
         // Gross way of unwrapping the Activity so we can get the FragmentManager
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialog.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialog.java
index cc7c3d5..aeb4408 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialog.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialog.java
@@ -20,7 +20,9 @@
 import static com.android.support.mediarouter.media.MediaRouter.RouteInfo.CONNECTION_STATE_CONNECTING;
 
 import android.annotation.NonNull;
+import android.app.Dialog;
 import android.content.Context;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
@@ -31,6 +33,7 @@
 import android.support.v7.app.AppCompatDialog;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -41,6 +44,7 @@
 import android.widget.ListView;
 import android.widget.TextView;
 
+import com.android.media.update.ApiHelper;
 import com.android.media.update.R;
 import com.android.support.mediarouter.media.MediaRouteSelector;
 import com.android.support.mediarouter.media.MediaRouter;
@@ -61,7 +65,7 @@
  * @see MediaRouteButton
  * @see MediaRouteActionProvider
  */
-public class MediaRouteChooserDialog extends AppCompatDialog {
+public class MediaRouteChooserDialog extends Dialog {
     static final String TAG = "MediaRouteChooserDialog";
 
     // Do not update the route list immediately to avoid unnatural dialog change.
@@ -94,8 +98,9 @@
     }
 
     public MediaRouteChooserDialog(Context context, int theme) {
-        super(context = MediaRouterThemeHelper.createThemedDialogContext(context, theme, false),
-                MediaRouterThemeHelper.createThemedDialogStyle(context));
+        super(new ContextThemeWrapper(context,
+                ApiHelper.getLibTheme(MediaRouterThemeHelper.getRouterThemeId(context))),
+                theme == 0 ? android.R.style.Animation : theme);
         context = getContext();
 
         mRouter = MediaRouter.getInstance(context);
@@ -182,7 +187,9 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        setContentView(R.layout.mr_chooser_dialog);
+        setContentView(ApiHelper.inflateLibLayout(getContext(),
+                ApiHelper.getLibTheme(MediaRouterThemeHelper.getRouterThemeId(getContext())),
+                R.layout.mr_chooser_dialog));
 
         mRoutes = new ArrayList<>();
         mAdapter = new RouteAdapter(getContext(), mRoutes);
@@ -199,7 +206,7 @@
      * Sets the width of the dialog. Also called when configuration changes.
      */
     void updateLayout() {
-        getWindow().setLayout(MediaRouteDialogHelper.getDialogWidth(getContext()),
+        getWindow().setLayout(MediaRouteDialogHelper.getDialogWidth(),
                 ViewGroup.LayoutParams.WRAP_CONTENT);
     }
 
@@ -248,7 +255,6 @@
 
     private final class RouteAdapter extends ArrayAdapter<MediaRouter.RouteInfo>
             implements ListView.OnItemClickListener {
-        private final LayoutInflater mInflater;
         private final Drawable mDefaultIcon;
         private final Drawable mTvIcon;
         private final Drawable mSpeakerIcon;
@@ -256,12 +262,16 @@
 
         public RouteAdapter(Context context, List<MediaRouter.RouteInfo> routes) {
             super(context, 0, routes);
-            mInflater = LayoutInflater.from(context);
-            TypedArray styledAttributes = getContext().obtainStyledAttributes(new int[] {
-                    R.attr.mediaRouteDefaultIconDrawable,
-                    R.attr.mediaRouteTvIconDrawable,
-                    R.attr.mediaRouteSpeakerIconDrawable,
-                    R.attr.mediaRouteSpeakerGroupIconDrawable});
+
+            TypedArray styledAttributes = ApiHelper.getLibTheme(
+                    MediaRouterThemeHelper.getRouterThemeId(context)).obtainStyledAttributes(
+                            new int[] {
+                                R.attr.mediaRouteDefaultIconDrawable,
+                                R.attr.mediaRouteTvIconDrawable,
+                                R.attr.mediaRouteSpeakerIconDrawable,
+                                R.attr.mediaRouteSpeakerGroupIconDrawable
+                            });
+
             mDefaultIcon = styledAttributes.getDrawable(0);
             mTvIcon = styledAttributes.getDrawable(1);
             mSpeakerIcon = styledAttributes.getDrawable(2);
@@ -283,7 +293,10 @@
         public View getView(int position, View convertView, ViewGroup parent) {
             View view = convertView;
             if (view == null) {
-                view = mInflater.inflate(R.layout.mr_chooser_list_item, parent, false);
+                view = ApiHelper.inflateLibLayout(getContext(),
+                        ApiHelper.getLibTheme(
+                                MediaRouterThemeHelper.getRouterThemeId(getContext())),
+                        R.layout.mr_chooser_list_item, parent, false);
             }
 
             MediaRouter.RouteInfo route = getItem(position);
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialogFragment.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialogFragment.java
index 2f85fb3..65e6b29 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialogFragment.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteChooserDialogFragment.java
@@ -17,10 +17,10 @@
 package com.android.support.mediarouter.app;
 
 import android.app.Dialog;
+import android.app.DialogFragment;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
 
 import com.android.support.mediarouter.media.MediaRouteSelector;
 
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialog.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialog.java
index 942797b..123ab21 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialog.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialog.java
@@ -455,7 +455,7 @@
      * Sets the width of the dialog. Also called when configuration changes.
      */
     void updateLayout() {
-        int width = MediaRouteDialogHelper.getDialogWidth(mContext);
+        int width = MediaRouteDialogHelper.getDialogWidth();
         getWindow().setLayout(width, ViewGroup.LayoutParams.WRAP_CONTENT);
 
         View decorView = getWindow().getDecorView();
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialogFragment.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialogFragment.java
index 9442df7..215d74f 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialogFragment.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteControllerDialogFragment.java
@@ -17,10 +17,10 @@
 package com.android.support.mediarouter.app;
 
 import android.app.Dialog;
+import android.app.DialogFragment;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.os.Bundle;
-import android.support.v4.app.DialogFragment;
 
 /**
  * Media route controller dialog fragment.
diff --git a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteDialogHelper.java b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteDialogHelper.java
index 6f75b46..62c050b 100644
--- a/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteDialogHelper.java
+++ b/packages/MediaComponents/src/com/android/support/mediarouter/app/MediaRouteDialogHelper.java
@@ -28,6 +28,7 @@
 import android.widget.ArrayAdapter;
 import android.widget.ListView;
 
+import com.android.media.update.ApiHelper;
 import com.android.media.update.R;
 
 import java.util.HashMap;
@@ -40,12 +41,12 @@
      * The framework should set the dialog width properly, but somehow it doesn't work, hence
      * duplicating a similar logic here to determine the appropriate dialog width.
      */
-    public static int getDialogWidth(Context context) {
-        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
+    public static int getDialogWidth() {
+        DisplayMetrics metrics = ApiHelper.getLibResources().getDisplayMetrics();
         boolean isPortrait = metrics.widthPixels < metrics.heightPixels;
 
         TypedValue value = new TypedValue();
-        context.getResources().getValue(isPortrait ? R.dimen.mr_dialog_fixed_width_minor
+        ApiHelper.getLibResources().getValue(isPortrait ? R.dimen.mr_dialog_fixed_width_minor
                 : R.dimen.mr_dialog_fixed_width_major, value, true);
         if (value.type == TypedValue.TYPE_DIMENSION) {
             return (int) value.getDimension(metrics);
diff --git a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
index 1cdaaee..dfc0792 100644
--- a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
@@ -29,7 +29,6 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityManager;
 import android.widget.Button;
 import android.widget.ImageButton;
 import android.widget.MediaControlView2;
@@ -64,8 +63,6 @@
     private static final int REWIND_TIME_MS = 10000;
     private static final int FORWARD_TIME_MS = 30000;
 
-    private AccessibilityManager mAccessibilityManager;
-
     private MediaController mController;
     private MediaController.TransportControls mControls;
     private PlaybackState mPlaybackState;
@@ -76,7 +73,6 @@
     private int mDuration;
     private int mPrevState;
     private int mCurrentVisibility;
-    private long mTimeout;
     private long mPlaybackActions;
     private boolean mShowing;
     private boolean mDragging;
@@ -122,14 +118,9 @@
 
     @Override
     public void initialize(@Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        mAccessibilityManager = AccessibilityManager.getInstance(mInstance.getContext());
-
         // Inflate MediaControlView2 from XML
         View root = makeControllerView();
         mInstance.addView(root);
-
-        // Set default timeout
-        mTimeout = 2000;
     }
 
     @Override
@@ -223,16 +214,6 @@
     }
 
     @Override
-    public void setTimeout_impl(long timeout) {
-        mTimeout = timeout;
-    }
-
-    @Override
-    public long getTimeout_impl() {
-        return mTimeout;
-    }
-
-    @Override
     public CharSequence getAccessibilityClassName_impl() {
         return MediaControlView2.class.getName();
     }
@@ -245,7 +226,6 @@
     // TODO: Should this function be removed?
     @Override
     public boolean onTrackballEvent_impl(MotionEvent ev) {
-        resetFadeOutRunnable();
         return false;
     }
 
@@ -290,11 +270,8 @@
                 // was already true.  This happens, for example, if we're
                 // paused with the progress bar showing the user hits play.
                 mInstance.post(mShowProgress);
-                resetFadeOutRunnable();
             } else if (visibility == View.GONE) {
                 mInstance.removeCallbacks(mShowProgress);
-                // Remove existing call to mFadeOut to avoid from being called later.
-                mInstance.removeCallbacks(mFadeOut);
             }
         }
     }
@@ -488,15 +465,6 @@
         }
     }
 
-    private final Runnable mFadeOut = new Runnable() {
-        @Override
-        public void run() {
-            if (isPlaying()) {
-                mInstance.setVisibility(View.GONE);
-            }
-        }
-    };
-
     private final Runnable mShowProgress = new Runnable() {
         @Override
         public void run() {
@@ -508,13 +476,6 @@
         }
     };
 
-    private void resetFadeOutRunnable() {
-        if (mTimeout != 0 && !mAccessibilityManager.isTouchExplorationEnabled()) {
-            mInstance.removeCallbacks(mFadeOut);
-            mInstance.postDelayed(mFadeOut, mTimeout);
-        }
-    }
-
     private String stringForTime(int timeMs) {
         int totalSeconds = timeMs / 1000;
 
@@ -590,7 +551,6 @@
             }
 
             mDragging = true;
-            mInstance.removeCallbacks(mFadeOut);
 
             // By removing these pending progress messages we make sure
             // that a) we won't update the progress while the user adjusts
@@ -639,8 +599,6 @@
 
             setProgress();
 
-            resetFadeOutRunnable();
-
             // Ensure that progress is properly updated in the future,
             // the call to show() does not guarantee this because it is a
             // no-op if we are already showing.
@@ -652,7 +610,6 @@
         @Override
         public void onClick(View v) {
             togglePausePlayState();
-            resetFadeOutRunnable();
         }
     };
 
@@ -662,8 +619,6 @@
             int pos = getCurrentPosition() - REWIND_TIME_MS;
             mControls.seekTo(pos);
             setProgress();
-
-            resetFadeOutRunnable();
         }
     };
 
@@ -673,8 +628,6 @@
             int pos = getCurrentPosition() + FORWARD_TIME_MS;
             mControls.seekTo(pos);
             setProgress();
-
-            resetFadeOutRunnable();
         }
     };
 
@@ -682,7 +635,6 @@
         @Override
         public void onClick(View v) {
             mControls.skipToNext();
-            resetFadeOutRunnable();
         }
     };
 
@@ -690,7 +642,6 @@
         @Override
         public void onClick(View v) {
             mControls.skipToPrevious();
-            resetFadeOutRunnable();
         }
     };
 
@@ -710,7 +661,6 @@
                 mController.sendCommand(MediaControlView2.COMMAND_HIDE_SUBTITLE, null, null);
                 mSubtitleIsEnabled = false;
             }
-            resetFadeOutRunnable();
         }
     };
 
@@ -732,7 +682,6 @@
             mController.sendCommand(MediaControlView2.COMMAND_SET_FULLSCREEN, args, null);
 
             mIsFullScreen = isEnteringFullScreen;
-            resetFadeOutRunnable();
         }
     };
 
@@ -741,7 +690,6 @@
         public void onClick(View v) {
             mBasicControls.setVisibility(View.GONE);
             mExtraControls.setVisibility(View.VISIBLE);
-            resetFadeOutRunnable();
         }
     };
 
@@ -750,7 +698,6 @@
         public void onClick(View v) {
             mBasicControls.setVisibility(View.VISIBLE);
             mExtraControls.setVisibility(View.GONE);
-            resetFadeOutRunnable();
         }
     };
 
diff --git a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
index 9f207b1..256003f 100644
--- a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
@@ -49,6 +49,7 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup.LayoutParams;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.MediaControlView2;
 import android.widget.VideoView2;
 
@@ -70,6 +71,7 @@
         implements VideoView2Provider, VideoViewInterface.SurfaceListener {
     private static final String TAG = "VideoView2";
     private static final boolean DEBUG = true; // STOPSHIP: Log.isLoggable(TAG, Log.DEBUG);
+    private static final long DEFAULT_SHOW_CONTROLLER_INTERVAL_MS = 2000;
 
     private final VideoView2 mInstance;
 
@@ -81,6 +83,9 @@
     private static final int STATE_PAUSED = 4;
     private static final int STATE_PLAYBACK_COMPLETED = 5;
 
+    private static final int INVALID_TRACK_INDEX = -1;
+
+    private AccessibilityManager mAccessibilityManager;
     private AudioManager mAudioManager;
     private AudioAttributes mAudioAttributes;
     private int mAudioFocusType = AudioManager.AUDIOFOCUS_GAIN; // legacy focus gain
@@ -117,15 +122,17 @@
     private int mVideoWidth;
     private int mVideoHeight;
 
-    private boolean mCCEnabled;
-    private int mSelectedTrackIndex;
-
     private SubtitleView mSubtitleView;
+    private boolean mSubtitleEnabled;
+    private int mSelectedTrackIndex;  // selected subtitle track index as MediaPlayer2 returns
+
     private float mSpeed;
     // TODO: Remove mFallbackSpeed when integration with MediaPlayer2's new setPlaybackParams().
     // Refer: https://docs.google.com/document/d/1nzAfns6i2hJ3RkaUre3QMT6wsDedJ5ONLiA_OOBFFX8/edit
     private float mFallbackSpeed;  // keep the original speed before 'pause' is called.
 
+    private long mShowControllerIntervalMs;
+
     public VideoView2Impl(VideoView2 instance,
             ViewGroupProvider superProvider, ViewGroupProvider privateProvider) {
         super(instance, superProvider, privateProvider);
@@ -138,6 +145,11 @@
         mVideoHeight = 0;
         mSpeed = 1.0f;
         mFallbackSpeed = mSpeed;
+        mSelectedTrackIndex = INVALID_TRACK_INDEX;
+        // TODO: add attributes to get this value.
+        mShowControllerIntervalMs = DEFAULT_SHOW_CONTROLLER_INTERVAL_MS;
+
+        mAccessibilityManager = AccessibilityManager.getInstance(mInstance.getContext());
 
         mAudioManager = (AudioManager) mInstance.getContext()
                 .getSystemService(Context.AUDIO_SERVICE);
@@ -179,11 +191,11 @@
         if (enableControlView) {
             mMediaControlView = new MediaControlView2(mInstance.getContext());
         }
-        boolean showSubtitle = (attrs == null) || attrs.getAttributeBooleanValue(
+        boolean enableSubtitle = (attrs == null) || attrs.getAttributeBooleanValue(
                 "http://schemas.android.com/apk/res/android",
-                "showSubtitle", true);
-        if (showSubtitle) {
-            Log.d(TAG, "showSubtitle attribute is true.");
+                "enableSubtitle", true);
+        if (enableSubtitle) {
+            Log.d(TAG, "enableSubtitle attribute is true.");
             // TODO: implement
         }
         int viewType = (attrs == null) ? VideoView2.VIEW_TYPE_SURFACEVIEW
@@ -200,8 +212,9 @@
     }
 
     @Override
-    public void setMediaControlView2_impl(MediaControlView2 mediaControlView) {
+    public void setMediaControlView2_impl(MediaControlView2 mediaControlView, long intervalMs) {
         mMediaControlView = mediaControlView;
+        mShowControllerIntervalMs = intervalMs;
         if (mRouteSelector != null) {
             ((MediaControlView2Impl) mMediaControlView.getProvider())
                     .setRouteSelector(mRouteSelector);
@@ -226,8 +239,8 @@
     }
 
     @Override
-    public void showSubtitle_impl(boolean show) {
-        if (show) {
+    public void setSubtitleEnabled_impl(boolean enable) {
+        if (enable) {
             // Retrieve all tracks that belong to the current video.
             MediaPlayer.TrackInfo[] trackInfos = mMediaPlayer.getTrackInfo();
 
@@ -240,16 +253,21 @@
             }
             if (subtitleTrackIndices.size() > 0) {
                 // Select first subtitle track
-                mCCEnabled = true;
                 mSelectedTrackIndex = subtitleTrackIndices.get(0);
                 mMediaPlayer.selectTrack(mSelectedTrackIndex);
             }
         } else {
-            if (mCCEnabled) {
+            if (mSelectedTrackIndex != INVALID_TRACK_INDEX) {
                 mMediaPlayer.deselectTrack(mSelectedTrackIndex);
-                mCCEnabled = false;
+                mSelectedTrackIndex = INVALID_TRACK_INDEX;
             }
         }
+        mSubtitleEnabled = enable;
+    }
+
+    @Override
+    public boolean isSubtitleEnabled_impl() {
+        return mSubtitleEnabled;
     }
 
     // TODO: remove setSpeed_impl once MediaController2 is ready.
@@ -431,8 +449,7 @@
             Log.d(TAG, "onTouchEvent(). mCurrentState=" + mCurrentState
                     + ", mTargetState=" + mTargetState);
         }
-        if (ev.getAction() == MotionEvent.ACTION_UP
-                && isInPlaybackState() && mMediaControlView != null) {
+        if (ev.getAction() == MotionEvent.ACTION_UP && mMediaControlView != null) {
             toggleMediaControlViewVisibility();
         }
 
@@ -441,14 +458,19 @@
 
     @Override
     public boolean onTrackballEvent_impl(MotionEvent ev) {
-        if (ev.getAction() == MotionEvent.ACTION_UP
-                && isInPlaybackState() && mMediaControlView != null) {
+        if (ev.getAction() == MotionEvent.ACTION_UP && mMediaControlView != null) {
             toggleMediaControlViewVisibility();
         }
 
         return super.onTrackballEvent_impl(ev);
     }
 
+    @Override
+    public boolean dispatchTouchEvent_impl(MotionEvent ev) {
+        // TODO: Test touch event handling logic thoroughly and simplify the logic.
+        return super.dispatchTouchEvent_impl(ev);
+    }
+
     ///////////////////////////////////////////////////
     // Implements VideoViewInterface.SurfaceListener
     ///////////////////////////////////////////////////
@@ -471,9 +493,6 @@
             Log.d(TAG, "onSurfaceDestroyed(). mCurrentState=" + mCurrentState
                     + ", mTargetState=" + mTargetState + ", " + view.toString());
         }
-        if (mMediaControlView != null) {
-            mMediaControlView.setVisibility(View.GONE);
-        }
     }
 
     @Override
@@ -661,8 +680,12 @@
         }
         mStateBuilder.setState(getCorrespondingPlaybackState(),
                 mMediaPlayer.getCurrentPosition(), mSpeed);
-        mStateBuilder.setBufferedPosition(
-                (long) (mCurrentBufferPercentage / 100.0) * mMediaPlayer.getDuration());
+        if (mCurrentState != STATE_ERROR
+            && mCurrentState != STATE_IDLE
+            && mCurrentState != STATE_PREPARING) {
+            mStateBuilder.setBufferedPosition(
+                    (long) (mCurrentBufferPercentage / 100.0) * mMediaPlayer.getDuration());
+        }
 
         // Set PlaybackState for MediaSession
         if (mMediaSession != null) {
@@ -692,11 +715,34 @@
         }
     }
 
+    private final Runnable mFadeOut = new Runnable() {
+        @Override
+        public void run() {
+            if (mCurrentState == STATE_PLAYING) {
+                mMediaControlView.setVisibility(View.GONE);
+            }
+        }
+    };
+
+    private void showController() {
+        // TODO: Decide what to show when the state is not in playback state
+        if (mMediaControlView == null || !isInPlaybackState()) {
+            return;
+        }
+        mMediaControlView.removeCallbacks(mFadeOut);
+        mMediaControlView.setVisibility(View.VISIBLE);
+        if (mShowControllerIntervalMs != 0
+            && !mAccessibilityManager.isTouchExplorationEnabled()) {
+            mMediaControlView.postDelayed(mFadeOut, mShowControllerIntervalMs);
+        }
+    }
+
     private void toggleMediaControlViewVisibility() {
         if (mMediaControlView.getVisibility() == View.VISIBLE) {
+            mMediaControlView.removeCallbacks(mFadeOut);
             mMediaControlView.setVisibility(View.GONE);
         } else {
-            mMediaControlView.setVisibility(View.VISIBLE);
+            showController();
         }
     }
 
@@ -757,6 +803,9 @@
                         + ", mTargetState=" + mTargetState);
             }
             mCurrentState = STATE_PREPARED;
+            // Create and set playback state for MediaControlView2
+            updatePlaybackState();
+
             if (mOnPreparedListener != null) {
                 mOnPreparedListener.onPrepared(mInstance);
             }
@@ -790,19 +839,6 @@
 
                 if (needToStart()) {
                     mMediaController.getTransportControls().play();
-                    if (mMediaControlView != null) {
-                        mMediaControlView.setVisibility(View.VISIBLE);
-                    }
-                } else if (!(isInPlaybackState() && mMediaPlayer.isPlaying())
-                        && (seekToPosition != 0 || mMediaPlayer.getCurrentPosition() > 0)) {
-                    if (mMediaControlView != null) {
-                        // Show the media controls when we're paused into a video and
-                        // make them stick.
-                        long currTimeout = mMediaControlView.getTimeout();
-                        mMediaControlView.setTimeout(0L);
-                        mMediaControlView.setVisibility(View.VISIBLE);
-                        mMediaControlView.setTimeout(currTimeout);
-                    }
                 }
             } else {
                 // We don't know the video size yet, but should start anyway.
@@ -811,8 +847,6 @@
                     mMediaController.getTransportControls().play();
                 }
             }
-            // Create and set playback state for MediaControlView2
-            updatePlaybackState();
 
             // Get and set duration and title values as MediaMetadata for MediaControlView2
             MediaMetadata.Builder builder = new MediaMetadata.Builder();
@@ -928,10 +962,10 @@
             } else {
                 switch (command) {
                     case MediaControlView2.COMMAND_SHOW_SUBTITLE:
-                        mInstance.showSubtitle(true);
+                        mInstance.setSubtitleEnabled(true);
                         break;
                     case MediaControlView2.COMMAND_HIDE_SUBTITLE:
-                        mInstance.showSubtitle(false);
+                        mInstance.setSubtitleEnabled(false);
                         break;
                     case MediaControlView2.COMMAND_SET_FULLSCREEN:
                         if (mOnFullScreenRequestListener != null) {
@@ -942,11 +976,13 @@
                         break;
                 }
             }
+            showController();
         }
 
         @Override
         public void onCustomAction(String action, Bundle extras) {
             mOnCustomActionListener.onCustomAction(action, extras);
+            showController();
         }
 
         @Override
@@ -966,6 +1002,7 @@
                             + ", mTargetState=" + mTargetState);
                 }
             }
+            showController();
         }
 
         @Override
@@ -986,6 +1023,7 @@
                             + ", mTargetState=" + mTargetState);
                 }
             }
+            showController();
         }
 
         @Override
@@ -1001,6 +1039,7 @@
                     mSeekWhenPrepared = pos;
                 }
             }
+            showController();
         }
 
         @Override
@@ -1010,6 +1049,7 @@
             } else {
                 resetPlayer();
             }
+            showController();
         }
     }
 
diff --git a/packages/MediaComponents/src/com/android/widget/ViewGroupImpl.java b/packages/MediaComponents/src/com/android/widget/ViewGroupImpl.java
index 8598bb2..5a06826 100644
--- a/packages/MediaComponents/src/com/android/widget/ViewGroupImpl.java
+++ b/packages/MediaComponents/src/com/android/widget/ViewGroupImpl.java
@@ -96,6 +96,11 @@
     }
 
     @Override
+    public boolean dispatchTouchEvent_impl(MotionEvent ev) {
+        return mSuperProvider.dispatchTouchEvent_impl(ev);
+    }
+
+    @Override
     public boolean checkLayoutParams_impl(ViewGroup.LayoutParams p) {
         return mSuperProvider.checkLayoutParams_impl(p);
     }
diff --git a/packages/MediaComponents/test/AndroidManifest.xml b/packages/MediaComponents/test/AndroidManifest.xml
index 30bac87..48e4292 100644
--- a/packages/MediaComponents/test/AndroidManifest.xml
+++ b/packages/MediaComponents/test/AndroidManifest.xml
@@ -20,14 +20,7 @@
     <application android:label="Media API Test">
         <uses-library android:name="android.test.runner" />
 
-        <activity android:name="android.widget2.VideoView2TestActivity"
-                  android:configChanges="keyboardHidden|orientation|screenSize"
-                  android:label="VideoView2TestActivity">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
-            </intent-filter>
-          </activity>
+        <activity android:name="android.media.MockActivity" />
 
         <!-- Keep the test services synced together with the TestUtils.java -->
         <service android:name="android.media.MockMediaSessionService2">
diff --git a/packages/MediaComponents/test/src/android/media/MediaController2Test.java b/packages/MediaComponents/test/src/android/media/MediaController2Test.java
index e8eaa20..07baf58 100644
--- a/packages/MediaComponents/test/src/android/media/MediaController2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaController2Test.java
@@ -16,14 +16,16 @@
 
 package android.media;
 
-import android.media.MediaController2.ControllerCallback;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
 import android.media.MediaPlayerInterface.PlaybackListener;
 import android.media.MediaSession2.Command;
 import android.media.MediaSession2.ControllerInfo;
 import android.media.MediaSession2.PlaylistParams;
 import android.media.MediaSession2.SessionCallback;
 import android.media.TestUtils.SyncHandler;
-import android.media.session.PlaybackState;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -57,7 +59,9 @@
 @FlakyTest
 public class MediaController2Test extends MediaSession2TestBase {
     private static final String TAG = "MediaController2Test";
+    private static final int DEFAULT_RATING_TYPE = Rating2.RATING_5_STARS;
 
+    PendingIntent mIntent;
     MediaSession2 mSession;
     MediaController2 mController;
     MockPlayer mPlayer;
@@ -66,10 +70,15 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
+        final Intent sessionActivity = new Intent(mContext, MockActivity.class);
         // Create this test specific MediaSession2 to use our own Handler.
+        mIntent = PendingIntent.getActivity(mContext, 0, sessionActivity, 0);
+
         mPlayer = new MockPlayer(1);
         mSession = new MediaSession2.Builder(mContext, mPlayer)
                 .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext))
+                .setRatingType(DEFAULT_RATING_TYPE)
+                .setSessionActivity(mIntent)
                 .setId(TAG).build();
         mController = createController(mSession.getToken());
         TestServiceRegistry.getInstance().setHandler(sHandler);
@@ -200,6 +209,18 @@
     }
 
     @Test
+    public void testGetRatingType() throws InterruptedException {
+        assertEquals(DEFAULT_RATING_TYPE, mController.getRatingType());
+    }
+
+    @Test
+    public void testGetSessionActivity() throws InterruptedException {
+        PendingIntent sessionActivity = mController.getSessionActivity();
+        assertEquals(mContext.getPackageName(), sessionActivity.getCreatorPackage());
+        assertEquals(Process.myUid(), sessionActivity.getCreatorUid());
+    }
+
+    @Test
     public void testGetSetPlaylistParams() throws Exception {
         final PlaylistParams params = new PlaylistParams(mContext,
                 PlaylistParams.REPEAT_MODE_ALL,
@@ -224,34 +245,64 @@
     }
 
     @Test
+    public void testSetVolumeTo() throws Exception {
+        final int maxVolume = 100;
+        final int currentVolume = 23;
+        final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+        TestVolumeProvider volumeProvider =
+                new TestVolumeProvider(mContext, volumeControlType, maxVolume, currentVolume);
+
+        mSession.setPlayer(new MockPlayer(0), volumeProvider);
+        final MediaController2 controller = createController(mSession.getToken(), true, null);
+
+        final int targetVolume = 50;
+        controller.setVolumeTo(targetVolume, 0 /* flags */);
+        assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertTrue(volumeProvider.mSetVolumeToCalled);
+        assertEquals(targetVolume, volumeProvider.mVolume);
+    }
+
+    @Test
+    public void testAdjustVolume() throws Exception {
+        final int maxVolume = 100;
+        final int currentVolume = 23;
+        final int volumeControlType = VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+        TestVolumeProvider volumeProvider =
+                new TestVolumeProvider(mContext, volumeControlType, maxVolume, currentVolume);
+
+        mSession.setPlayer(new MockPlayer(0), volumeProvider);
+        final MediaController2 controller = createController(mSession.getToken(), true, null);
+
+        final int direction = AudioManager.ADJUST_RAISE;
+        controller.adjustVolume(direction, 0 /* flags */);
+        assertTrue(volumeProvider.mLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+        assertTrue(volumeProvider.mAdjustVolumeCalled);
+        assertEquals(direction, volumeProvider.mDirection);
+    }
+
+    @Test
     public void testGetPackageName() {
         assertEquals(mContext.getPackageName(), mController.getSessionToken().getPackageName());
     }
 
-    // This also tests testGetPlaybackState().
+    // This also tests getPlaybackState().
     @Test
     public void testControllerCallback_onPlaybackStateChanged() throws InterruptedException {
-        final CountDownLatch latch = new CountDownLatch(2);
+        final CountDownLatch latch = new CountDownLatch(1);
         final TestControllerCallbackInterface callback = new TestControllerCallbackInterface() {
             @Override
             public void onPlaybackStateChanged(PlaybackState2 state) {
-                switch ((int) latch.getCount()) {
-                    case 2:
-                        assertEquals(PlaybackState.STATE_PLAYING, state.getState());
-                        break;
-                    case 1:
-                        assertEquals(PlaybackState.STATE_PAUSED, state.getState());
-                        break;
-                }
+                // Called only once when the player's playback state is changed after this.
+                assertEquals(PlaybackState2.STATE_PAUSED, state.getState());
                 latch.countDown();
             }
         };
-
-        mPlayer.notifyPlaybackState(createPlaybackState(PlaybackState.STATE_PLAYING));
+        mPlayer.notifyPlaybackState(createPlaybackState(PlaybackState2.STATE_PLAYING));
         mController = createController(mSession.getToken(), true, callback);
-        mPlayer.notifyPlaybackState(createPlaybackState(PlaybackState.STATE_PAUSED));
+        assertEquals(PlaybackState2.STATE_PLAYING, mController.getPlaybackState().getState());
+        mPlayer.notifyPlaybackState(createPlaybackState(PlaybackState2.STATE_PAUSED));
         assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
-        assertEquals(PlaybackState.STATE_PAUSED, mController.getPlaybackState().getState());
+        assertEquals(PlaybackState2.STATE_PAUSED, mController.getPlaybackState().getState());
     }
 
     @Test
@@ -326,6 +377,151 @@
     }
 
     @Test
+    public void testPlayFromSearch() throws InterruptedException {
+        final String request = "random query";
+        final Bundle bundle = new Bundle();
+        bundle.putString("key", "value");
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback(mContext) {
+            @Override
+            public void onPlayFromSearch(ControllerInfo controller, String query, Bundle extras) {
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(request, query);
+                assertTrue(TestUtils.equals(bundle, extras));
+                latch.countDown();;
+            }
+        };
+        try (MediaSession2 session = new MediaSession2.Builder(mContext, mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testPlayFromSearch").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.playFromSearch(request, bundle);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testPlayFromUri() throws InterruptedException {
+        final Uri request = Uri.parse("foo://boo");
+        final Bundle bundle = new Bundle();
+        bundle.putString("key", "value");
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback(mContext) {
+            @Override
+            public void onPlayFromUri(ControllerInfo controller, Uri uri, Bundle extras) {
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(request, uri);
+                assertTrue(TestUtils.equals(bundle, extras));
+                latch.countDown();;
+            }
+        };
+        try (MediaSession2 session = new MediaSession2.Builder(mContext, mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testPlayFromUri").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.playFromUri(request, bundle);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testPlayFromMediaId() throws InterruptedException {
+        final String request = "media_id";
+        final Bundle bundle = new Bundle();
+        bundle.putString("key", "value");
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback(mContext) {
+            @Override
+            public void onPlayFromMediaId(ControllerInfo controller, String id, Bundle extras) {
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(request, id);
+                assertTrue(TestUtils.equals(bundle, extras));
+                latch.countDown();;
+            }
+        };
+        try (MediaSession2 session = new MediaSession2.Builder(mContext, mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testPlayFromMediaId").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.playFromMediaId(request, bundle);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+
+    @Test
+    public void testPrepareFromSearch() throws InterruptedException {
+        final String request = "random query";
+        final Bundle bundle = new Bundle();
+        bundle.putString("key", "value");
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback(mContext) {
+            @Override
+            public void onPrepareFromSearch(ControllerInfo controller, String query, Bundle extras) {
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(request, query);
+                assertTrue(TestUtils.equals(bundle, extras));
+                latch.countDown();;
+            }
+        };
+        try (MediaSession2 session = new MediaSession2.Builder(mContext, mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testPrepareFromSearch").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.prepareFromSearch(request, bundle);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testPrepareFromUri() throws InterruptedException {
+        final Uri request = Uri.parse("foo://boo");
+        final Bundle bundle = new Bundle();
+        bundle.putString("key", "value");
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback(mContext) {
+            @Override
+            public void onPrepareFromUri(ControllerInfo controller, Uri uri, Bundle extras) {
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(request, uri);
+                assertTrue(TestUtils.equals(bundle, extras));
+                latch.countDown();;
+            }
+        };
+        try (MediaSession2 session = new MediaSession2.Builder(mContext, mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testPrepareFromUri").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.prepareFromUri(request, bundle);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
+    public void testPrepareFromMediaId() throws InterruptedException {
+        final String request = "media_id";
+        final Bundle bundle = new Bundle();
+        bundle.putString("key", "value");
+        final CountDownLatch latch = new CountDownLatch(1);
+        final SessionCallback callback = new SessionCallback(mContext) {
+            @Override
+            public void onPrepareFromMediaId(ControllerInfo controller, String id, Bundle extras) {
+                assertEquals(mContext.getPackageName(), controller.getPackageName());
+                assertEquals(request, id);
+                assertTrue(TestUtils.equals(bundle, extras));
+                latch.countDown();;
+            }
+        };
+        try (MediaSession2 session = new MediaSession2.Builder(mContext, mPlayer)
+                .setSessionCallback(sHandlerExecutor, callback)
+                .setId("testPrepareFromMediaId").build()) {
+            MediaController2 controller = createController(session.getToken());
+            controller.prepareFromMediaId(request, bundle);
+            assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        }
+    }
+
+    @Test
     public void testIsConnected() throws InterruptedException {
         assertTrue(mController.isConnected());
         sHandler.postAndSync(()->{
@@ -364,7 +560,7 @@
             });
             final MediaController2 controller = createController(mSession.getToken());
             testHandler.post(() -> {
-                final PlaybackState2 state = createPlaybackState(PlaybackState.STATE_ERROR);
+                final PlaybackState2 state = createPlaybackState(PlaybackState2.STATE_ERROR);
                 for (int i = 0; i < 100; i++) {
                     // triggers call from session to controller.
                     player.notifyPlaybackState(state);
@@ -461,11 +657,14 @@
         */
     }
 
+    // TODO(jaewan): Re-enable after b/72792686 is fixed
+    @Ignore
     @Test
     public void testControllerAfterSessionIsGone_session() throws InterruptedException {
         testControllerAfterSessionIsGone(mSession.getToken().getId());
     }
 
+    // TODO(jaewan): Re-enable after b/72792686 is fixed
     @Ignore
     @Test
     public void testControllerAfterSessionIsGone_sessionService() throws InterruptedException {
@@ -570,4 +769,31 @@
 
     // TODO(jaewan): Add  test for service connect rejection, when we differentiate session
     //               active/inactive and connection accept/refuse
+
+    class TestVolumeProvider extends VolumeProvider2 {
+        final CountDownLatch mLatch = new CountDownLatch(1);
+        boolean mSetVolumeToCalled;
+        boolean mAdjustVolumeCalled;
+        int mVolume;
+        int mDirection;
+
+        public TestVolumeProvider(Context context, int controlType, int maxVolume,
+                int currentVolume) {
+            super(context, controlType, maxVolume, currentVolume);
+        }
+
+        @Override
+        public void onSetVolumeTo(int volume) {
+            mSetVolumeToCalled = true;
+            mVolume = volume;
+            mLatch.countDown();
+        }
+
+        @Override
+        public void onAdjustVolume(int direction) {
+            mAdjustVolumeCalled = true;
+            mDirection = direction;
+            mLatch.countDown();
+        }
+    }
 }
diff --git a/packages/MediaComponents/test/src/android/media/MediaSession2Test.java b/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
index 43a6c2c..b00633b 100644
--- a/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
@@ -27,6 +27,9 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 
+import android.content.Context;
+import android.media.AudioManager;
+import android.media.MediaController2.PlaybackInfo;
 import android.media.MediaPlayerInterface.PlaybackListener;
 import android.media.MediaSession2.Builder;
 import android.media.MediaSession2.Command;
@@ -99,17 +102,15 @@
 
     @Test
     public void testSetPlayer() throws Exception {
-        sHandler.postAndSync(() -> {
-            MockPlayer player = new MockPlayer(0);
-            // Test if setPlayer doesn't crash with various situations.
-            mSession.setPlayer(mPlayer);
-            mSession.setPlayer(player);
-            mSession.close();
-        });
+        MockPlayer player = new MockPlayer(0);
+        // Test if setPlayer doesn't crash with various situations.
+        mSession.setPlayer(mPlayer);
+        mSession.setPlayer(player);
+        mSession.close();
     }
 
     @Test
-    public void testSetPlayerWithVolumeProvider() throws Exception {
+    public void testSetPlayer_playbackInfo() throws Exception {
         MockPlayer player = new MockPlayer(0);
         AudioAttributes attrs = new AudioAttributes.Builder()
                 .setContentType(CONTENT_TYPE_MUSIC)
@@ -125,7 +126,7 @@
         final CountDownLatch latch = new CountDownLatch(1);
         final TestControllerCallbackInterface callback = new TestControllerCallbackInterface() {
             @Override
-            public void onPlaybackInfoChanged(MediaController2.PlaybackInfo info) {
+            public void onPlaybackInfoChanged(PlaybackInfo info) {
                 assertEquals(MediaController2.PlaybackInfo.PLAYBACK_TYPE_REMOTE,
                         info.getPlaybackType());
                 assertEquals(attrs, info.getAudioAttributes());
@@ -136,18 +137,30 @@
             }
         };
 
+        mSession.setPlayer(player);
+
         final MediaController2 controller = createController(mSession.getToken(), true, callback);
-        assertNull(controller.getPlaybackInfo());
+        PlaybackInfo info = controller.getPlaybackInfo();
+        assertNotNull(info);
+        assertEquals(PlaybackInfo.PLAYBACK_TYPE_LOCAL, info.getPlaybackType());
+        assertEquals(attrs, info.getAudioAttributes());
+        AudioManager manager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+        int localVolumeControlType = manager.isVolumeFixed()
+                ? VolumeProvider2.VOLUME_CONTROL_FIXED : VolumeProvider2.VOLUME_CONTROL_ABSOLUTE;
+        assertEquals(localVolumeControlType, info.getControlType());
+        assertEquals(manager.getStreamMaxVolume(AudioManager.STREAM_MUSIC), info.getMaxVolume());
+        assertEquals(manager.getStreamVolume(AudioManager.STREAM_MUSIC), info.getCurrentVolume());
 
         mSession.setPlayer(player, volumeProvider);
         assertTrue(latch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
 
-        MediaController2.PlaybackInfo infoOut = controller.getPlaybackInfo();
-        assertEquals(MediaController2.PlaybackInfo.PLAYBACK_TYPE_REMOTE, infoOut.getPlaybackType());
-        assertEquals(attrs, infoOut.getAudioAttributes());
-        assertEquals(volumeControlType, infoOut.getPlaybackType());
-        assertEquals(maxVolume, infoOut.getMaxVolume());
-        assertEquals(currentVolume, infoOut.getCurrentVolume());
+        info = controller.getPlaybackInfo();
+        assertNotNull(info);
+        assertEquals(PlaybackInfo.PLAYBACK_TYPE_REMOTE, info.getPlaybackType());
+        assertEquals(attrs, info.getAudioAttributes());
+        assertEquals(volumeControlType, info.getControlType());
+        assertEquals(maxVolume, info.getMaxVolume());
+        assertEquals(currentVolume, info.getCurrentVolume());
     }
 
     @Test
diff --git a/packages/MediaComponents/test/src/android/media/MockActivity.java b/packages/MediaComponents/test/src/android/media/MockActivity.java
new file mode 100644
index 0000000..4627530
--- /dev/null
+++ b/packages/MediaComponents/test/src/android/media/MockActivity.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package android.media;
+
+import android.app.Activity;
+
+public class MockActivity extends Activity {
+}
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 1ebaea9..8e112a1 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -122,8 +122,7 @@
 }
 
 binder::Status CameraDeviceClient::insertGbpLocked(const sp<IGraphicBufferProducer>& gbp,
-        SurfaceMap* outSurfaceMap,
-        Vector<int32_t>* outputStreamIds) {
+        SurfaceMap* outSurfaceMap, Vector<int32_t>* outputStreamIds, int32_t *currentStreamId) {
     int idx = mStreamMap.indexOfKey(IInterface::asBinder(gbp));
 
     // Trying to submit request with surface that wasn't created
@@ -146,6 +145,10 @@
             __FUNCTION__, mCameraIdStr.string(), streamSurfaceId.streamId(),
             streamSurfaceId.surfaceId());
 
+    if (currentStreamId != nullptr) {
+        *currentStreamId = streamSurfaceId.streamId();
+    }
+
     return binder::Status::ok();
 }
 
@@ -218,40 +221,6 @@
                     "Invalid camera request settings");
         }
 
-        CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList;
-        for (const auto& it : request.mPhysicalCameraSettings) {
-            String8 physicalId(it.id.c_str());
-            if ((physicalId != mDevice->getId()) && !checkPhysicalCameraId(physicalId)) {
-                ALOGE("%s: Camera %s: Physical camera id: %s is invalid.", __FUNCTION__,
-                        mCameraIdStr.string(), physicalId.string());
-                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                        "Invalid physical camera id");
-            }
-
-            CameraMetadata metadata(it.settings);
-            if (metadata.isEmpty()) {
-                ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
-                        __FUNCTION__, mCameraIdStr.string());
-                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                        "Request settings are empty");
-            }
-
-            if (!enforceRequestPermissions(metadata)) {
-                // Callee logs
-                return STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
-                        "Caller does not have permission to change restricted controls");
-            }
-
-            physicalSettingsList.push_back({it.id, metadata});
-        }
-
-        if (streaming && (physicalSettingsList.size() > 1)) {
-            ALOGE("%s: Camera %s: Individual physical camera settings are not supported in "
-                    "streaming requests. Rejecting request.", __FUNCTION__, mCameraIdStr.string());
-            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                    "Streaming request contains individual physical requests");
-        }
-
         if (request.mSurfaceList.isEmpty() && request.mStreamIdxList.size() == 0) {
             ALOGE("%s: Camera %s: Requests must have at least one surface target. "
                     "Rejecting request.", __FUNCTION__, mCameraIdStr.string());
@@ -265,15 +234,26 @@
          */
         SurfaceMap surfaceMap;
         Vector<int32_t> outputStreamIds;
+        std::vector<std::string> requestedPhysicalIds;
         if (request.mSurfaceList.size() > 0) {
             for (sp<Surface> surface : request.mSurfaceList) {
                 if (surface == 0) continue;
 
+                int32_t streamId;
                 sp<IGraphicBufferProducer> gbp = surface->getIGraphicBufferProducer();
-                res = insertGbpLocked(gbp, &surfaceMap, &outputStreamIds);
+                res = insertGbpLocked(gbp, &surfaceMap, &outputStreamIds, &streamId);
                 if (!res.isOk()) {
                     return res;
                 }
+
+                ssize_t index = mConfiguredOutputs.indexOfKey(streamId);
+                if (index >= 0) {
+                    String8 requestedPhysicalId(
+                            mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
+                    requestedPhysicalIds.push_back(requestedPhysicalId.string());
+                } else {
+                    ALOGW("%s: Output stream Id not found among configured outputs!", __FUNCTION__);
+                }
             }
         } else {
             for (size_t i = 0; i < request.mStreamIdxList.size(); i++) {
@@ -298,13 +278,55 @@
                             "Request targets Surface has invalid surface index");
                 }
 
-                res = insertGbpLocked(gbps[surfaceIdx], &surfaceMap, &outputStreamIds);
+                res = insertGbpLocked(gbps[surfaceIdx], &surfaceMap, &outputStreamIds, nullptr);
                 if (!res.isOk()) {
                     return res;
                 }
+
+                String8 requestedPhysicalId(
+                        mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
+                requestedPhysicalIds.push_back(requestedPhysicalId.string());
             }
         }
 
+        CameraDeviceBase::PhysicalCameraSettingsList physicalSettingsList;
+        for (const auto& it : request.mPhysicalCameraSettings) {
+            String8 physicalId(it.id.c_str());
+            if (physicalId != mDevice->getId()) {
+                auto found = std::find(requestedPhysicalIds.begin(), requestedPhysicalIds.end(),
+                        it.id);
+                if (found == requestedPhysicalIds.end()) {
+                    ALOGE("%s: Camera %s: Physical camera id: %s not part of attached outputs.",
+                            __FUNCTION__, mCameraIdStr.string(), physicalId.string());
+                    return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                            "Invalid physical camera id");
+                }
+            }
+
+            CameraMetadata metadata(it.settings);
+            if (metadata.isEmpty()) {
+                ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
+                        __FUNCTION__, mCameraIdStr.string());
+                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                        "Request settings are empty");
+            }
+
+            physicalSettingsList.push_back({it.id, metadata});
+        }
+
+        if (streaming && (physicalSettingsList.size() > 1)) {
+            ALOGE("%s: Camera %s: Individual physical camera settings are not supported in "
+                    "streaming requests. Rejecting request.", __FUNCTION__, mCameraIdStr.string());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                    "Streaming request contains individual physical requests");
+        }
+
+        if (!enforceRequestPermissions(physicalSettingsList.begin()->metadata)) {
+            // Callee logs
+            return STATUS_ERROR(CameraService::ERROR_PERMISSION_DENIED,
+                    "Caller does not have permission to change restricted controls");
+        }
+
         physicalSettingsList.begin()->metadata.update(ANDROID_REQUEST_OUTPUT_STREAMS,
                 &outputStreamIds[0], outputStreamIds.size());
 
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 14aeed0..435c99d 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -259,8 +259,8 @@
 
     // Utility method to insert the surface into SurfaceMap
     binder::Status insertGbpLocked(const sp<IGraphicBufferProducer>& gbp,
-            /*out*/SurfaceMap* surfaceMap,
-            /*out*/Vector<int32_t>* streamIds);
+            /*out*/SurfaceMap* surfaceMap, /*out*/Vector<int32_t>* streamIds,
+            /*out*/int32_t*  currentStreamId);
 
     // Check that the physicalCameraId passed in is spported by the camera
     // device.