Merge "Remove show/hide API"
diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp
index 7ab0bcd..b5c1ddf 100644
--- a/drm/libmediadrm/DrmHal.cpp
+++ b/drm/libmediadrm/DrmHal.cpp
@@ -44,6 +44,8 @@
 using drm::V1_0::KeyValue;
 using drm::V1_1::HdcpLevel;;
 using drm::V1_0::SecureStop;
+using drm::V1_1::SecureStopRelease;
+using drm::V1_0::SecureStopId;
 using drm::V1_1::SecurityLevel;
 using drm::V1_0::Status;
 using ::android::hardware::hidl_array;
@@ -165,6 +167,15 @@
     return secureStops;
 }
 
+static List<Vector<uint8_t>> toSecureStopIds(const hidl_vec<SecureStopId>&
+        hSecureStopIds) {
+    List<Vector<uint8_t>> secureStopIds;
+    for (size_t i = 0; i < hSecureStopIds.size(); i++) {
+        secureStopIds.push_back(toVector(hSecureStopIds[i]));
+    }
+    return secureStopIds;
+}
+
 static status_t toStatusT(Status status) {
     switch (status) {
     case Status::OK:
@@ -797,6 +808,32 @@
 }
 
 
+status_t DrmHal::getSecureStopIds(List<Vector<uint8_t>> &secureStopIds) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    if (mPluginV1_1 == NULL) {
+        return ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    status_t err = UNKNOWN_ERROR;
+
+    Return<void> hResult = mPluginV1_1->getSecureStopIds(
+            [&](Status status, const hidl_vec<SecureStopId>& hSecureStopIds) {
+                if (status == Status::OK) {
+                    secureStopIds = toSecureStopIds(hSecureStopIds);
+                }
+                err = toStatusT(status);
+            }
+    );
+
+    return hResult.isOk() ? err : DEAD_OBJECT;
+}
+
+
 status_t DrmHal::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
@@ -819,13 +856,36 @@
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
+    if (mPluginV1_1 != NULL) {
+        SecureStopRelease secureStopRelease;
+        secureStopRelease.opaqueData = toHidlVec(ssRelease);
+        return toStatusT(mPluginV1_1->releaseSecureStops(secureStopRelease));
+    }
+
     return toStatusT(mPlugin->releaseSecureStop(toHidlVec(ssRelease)));
 }
 
-status_t DrmHal::releaseAllSecureStops() {
+status_t DrmHal::removeSecureStop(Vector<uint8_t> const &ssid) {
+    Mutex::Autolock autoLock(mLock);
+
+    if (mInitCheck != OK) {
+        return mInitCheck;
+    }
+
+    if (mPluginV1_1 == NULL) {
+        return ERROR_DRM_CANNOT_HANDLE;
+    }
+
+    return toStatusT(mPluginV1_1->removeSecureStop(toHidlVec(ssid)));
+}
+
+status_t DrmHal::removeAllSecureStops() {
     Mutex::Autolock autoLock(mLock);
     INIT_CHECK();
 
+    if (mPluginV1_1 != NULL) {
+        return toStatusT(mPluginV1_1->removeAllSecureStops());
+    }
     return toStatusT(mPlugin->releaseAllSecureStops());
 }
 
diff --git a/drm/libmediadrm/IDrm.cpp b/drm/libmediadrm/IDrm.cpp
index e7417cc..63a9562 100644
--- a/drm/libmediadrm/IDrm.cpp
+++ b/drm/libmediadrm/IDrm.cpp
@@ -56,11 +56,13 @@
     VERIFY,
     SET_LISTENER,
     GET_SECURE_STOP,
-    RELEASE_ALL_SECURE_STOPS,
+    REMOVE_ALL_SECURE_STOPS,
     GET_HDCP_LEVELS,
     GET_NUMBER_OF_SESSIONS,
     GET_SECURITY_LEVEL,
     SET_SECURITY_LEVEL,
+    REMOVE_SECURE_STOP,
+    GET_SECURE_STOP_IDS
 };
 
 struct BpDrm : public BpInterface<IDrm> {
@@ -302,6 +304,25 @@
         return reply.readInt32();
     }
 
+    virtual status_t getSecureStopIds(List<Vector<uint8_t> > &secureStopIds) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        status_t status = remote()->transact(GET_SECURE_STOP_IDS, data, &reply);
+        if (status != OK) {
+            return status;
+        }
+
+        secureStopIds.clear();
+        uint32_t count = reply.readInt32();
+        for (size_t i = 0; i < count; i++) {
+            Vector<uint8_t> secureStopId;
+            readVector(reply, secureStopId);
+            secureStopIds.push_back(secureStopId);
+        }
+        return reply.readInt32();
+    }
+
     virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
@@ -329,11 +350,24 @@
         return reply.readInt32();
     }
 
-    virtual status_t releaseAllSecureStops() {
+    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) {
         Parcel data, reply;
         data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 
-        status_t status = remote()->transact(RELEASE_ALL_SECURE_STOPS, data, &reply);
+        writeVector(data, ssid);
+        status_t status = remote()->transact(REMOVE_SECURE_STOP, data, &reply);
+        if (status != OK) {
+            return status;
+        }
+
+        return reply.readInt32();
+    }
+
+    virtual status_t removeAllSecureStops() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+        status_t status = remote()->transact(REMOVE_ALL_SECURE_STOPS, data, &reply);
         if (status != OK) {
             return status;
         }
@@ -854,6 +888,24 @@
             return OK;
         }
 
+        case GET_SECURE_STOP_IDS:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            List<Vector<uint8_t> > secureStopIds;
+            status_t result = getSecureStopIds(secureStopIds);
+            size_t count = secureStopIds.size();
+            reply->writeInt32(count);
+            List<Vector<uint8_t> >::iterator iter = secureStopIds.begin();
+            while(iter != secureStopIds.end()) {
+                size_t size = iter->size();
+                reply->writeInt32(size);
+                reply->write(iter->array(), iter->size());
+                iter++;
+            }
+            reply->writeInt32(result);
+            return OK;
+        }
+
         case GET_SECURE_STOP:
         {
             CHECK_INTERFACE(IDrm, data, reply);
@@ -874,10 +926,19 @@
             return OK;
         }
 
-        case RELEASE_ALL_SECURE_STOPS:
+        case REMOVE_SECURE_STOP:
         {
             CHECK_INTERFACE(IDrm, data, reply);
-            reply->writeInt32(releaseAllSecureStops());
+            Vector<uint8_t> ssid;
+            readVector(data, ssid);
+            reply->writeInt32(removeSecureStop(ssid));
+            return OK;
+        }
+
+        case REMOVE_ALL_SECURE_STOPS:
+        {
+            CHECK_INTERFACE(IDrm, data, reply);
+            reply->writeInt32(removeAllSecureStops());
             return OK;
         }
 
diff --git a/include/media/MediaSourceBase.h b/include/media/MediaSourceBase.h
new file mode 120000
index 0000000..fe227b1
--- /dev/null
+++ b/include/media/MediaSourceBase.h
@@ -0,0 +1 @@
+../../media/libmediaextractor/include/media/MediaSourceBase.h
\ No newline at end of file
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index dfb54e2..17d6aee 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -20,7 +20,7 @@
 
 #include "AACExtractor.h"
 #include <media/DataSource.h>
-#include <media/MediaSource.h>
+#include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/avc_utils.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/AMessage.h>
@@ -33,7 +33,7 @@
 
 namespace android {
 
-class AACSource : public MediaSource {
+class AACSource : public MediaSourceBase {
 public:
     AACSource(const sp<DataSource> &source,
               const sp<MetaData> &meta,
@@ -207,7 +207,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-sp<MediaSource> AACExtractor::getTrack(size_t index) {
+MediaSourceBase *AACExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
diff --git a/media/extractors/aac/AACExtractor.h b/media/extractors/aac/AACExtractor.h
index aede185..33fbba7 100644
--- a/media/extractors/aac/AACExtractor.h
+++ b/media/extractors/aac/AACExtractor.h
@@ -32,7 +32,7 @@
     AACExtractor(const sp<DataSource> &source, const sp<AMessage> &meta);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual MediaSourceBase *getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index b8967bd..10be50c 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -21,7 +21,7 @@
 #include "AMRExtractor.h"
 
 #include <media/DataSource.h>
-#include <media/MediaSource.h>
+#include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
@@ -31,7 +31,7 @@
 
 namespace android {
 
-class AMRSource : public MediaSource {
+class AMRSource : public MediaSourceBase {
 public:
     AMRSource(const sp<DataSource> &source,
               const sp<MetaData> &meta,
@@ -186,7 +186,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-sp<MediaSource> AMRExtractor::getTrack(size_t index) {
+MediaSourceBase *AMRExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
diff --git a/media/extractors/amr/AMRExtractor.h b/media/extractors/amr/AMRExtractor.h
index 79b22d6..56883e3 100644
--- a/media/extractors/amr/AMRExtractor.h
+++ b/media/extractors/amr/AMRExtractor.h
@@ -32,7 +32,7 @@
     explicit AMRExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual MediaSourceBase *getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/extractors/flac/FLACExtractor.cpp b/media/extractors/flac/FLACExtractor.cpp
index 0c88246..ba28e86 100644
--- a/media/extractors/flac/FLACExtractor.cpp
+++ b/media/extractors/flac/FLACExtractor.cpp
@@ -23,7 +23,7 @@
 #include "FLAC/stream_decoder.h"
 
 #include <media/DataSource.h>
-#include <media/MediaSource.h>
+#include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/base64.h>
@@ -161,7 +161,7 @@
 
 class FLACParser;
 
-class FLACSource : public MediaSource {
+class FLACSource : public MediaSourceBase {
 
 public:
     FLACSource(
@@ -936,7 +936,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-sp<MediaSource> FLACExtractor::getTrack(size_t index)
+MediaSourceBase *FLACExtractor::getTrack(size_t index)
 {
     if (mInitCheck != OK || index > 0) {
         return NULL;
diff --git a/media/extractors/flac/FLACExtractor.h b/media/extractors/flac/FLACExtractor.h
index 6907ceb..2e7ee3b 100644
--- a/media/extractors/flac/FLACExtractor.h
+++ b/media/extractors/flac/FLACExtractor.h
@@ -32,7 +32,7 @@
     explicit FLACExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual MediaSourceBase *getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index a8509fc..18b1d23 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -25,7 +25,7 @@
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MetaData.h>
-#include <media/MediaSource.h>
+#include <media/MediaSourceBase.h>
 #include <libsonivox/eas_reverb.h>
 
 namespace android {
@@ -33,7 +33,7 @@
 // how many Sonivox output buffers to aggregate into one MediaBuffer
 static const int NUM_COMBINE_BUFFERS = 4;
 
-class MidiSource : public MediaSource {
+class MidiSource : public MediaSourceBase {
 
 public:
     MidiSource(
@@ -282,7 +282,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-sp<MediaSource> MidiExtractor::getTrack(size_t index)
+MediaSourceBase *MidiExtractor::getTrack(size_t index)
 {
     if (mInitCheck != OK || index > 0) {
         return NULL;
diff --git a/media/extractors/midi/MidiExtractor.h b/media/extractors/midi/MidiExtractor.h
index 0fae94a..87e4654 100644
--- a/media/extractors/midi/MidiExtractor.h
+++ b/media/extractors/midi/MidiExtractor.h
@@ -56,7 +56,7 @@
     explicit MidiExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual MediaSourceBase *getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index e199f03..7baccb7 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -22,7 +22,7 @@
 #include "MatroskaExtractor.h"
 
 #include <media/DataSource.h>
-#include <media/MediaSource.h>
+#include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AUtils.h>
 #include <media/stagefright/foundation/ABuffer.h>
@@ -121,9 +121,8 @@
     BlockIterator &operator=(const BlockIterator &);
 };
 
-struct MatroskaSource : public MediaSource {
-    MatroskaSource(
-            const sp<MatroskaExtractor> &extractor, size_t index);
+struct MatroskaSource : public MediaSourceBase {
+    MatroskaSource(MatroskaExtractor *extractor, size_t index);
 
     virtual status_t start(MetaData *params);
     virtual status_t stop();
@@ -144,7 +143,7 @@
         OTHER
     };
 
-    sp<MatroskaExtractor> mExtractor;
+    MatroskaExtractor *mExtractor;
     size_t mTrackIndex;
     Type mType;
     bool mIsAudio;
@@ -211,12 +210,12 @@
 }
 
 MatroskaSource::MatroskaSource(
-        const sp<MatroskaExtractor> &extractor, size_t index)
+        MatroskaExtractor *extractor, size_t index)
     : mExtractor(extractor),
       mTrackIndex(index),
       mType(OTHER),
       mIsAudio(false),
-      mBlockIter(mExtractor.get(),
+      mBlockIter(mExtractor,
                  mExtractor->mTracks.itemAt(index).mTrackNum,
                  index),
       mNALSizeLen(-1) {
@@ -928,7 +927,7 @@
     return mTracks.size();
 }
 
-sp<MediaSource> MatroskaExtractor::getTrack(size_t index) {
+MediaSourceBase *MatroskaExtractor::getTrack(size_t index) {
     if (index >= mTracks.size()) {
         return NULL;
     }
diff --git a/media/extractors/mkv/MatroskaExtractor.h b/media/extractors/mkv/MatroskaExtractor.h
index 26f8d19..54419bf 100644
--- a/media/extractors/mkv/MatroskaExtractor.h
+++ b/media/extractors/mkv/MatroskaExtractor.h
@@ -38,7 +38,7 @@
 
     virtual size_t countTracks();
 
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual MediaSourceBase *getTrack(size_t index);
 
     virtual sp<MetaData> getTrackMetaData(
             size_t index, uint32_t flags);
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index f26ed25..7e27fd8 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -25,7 +25,7 @@
 #include "XINGSeeker.h"
 
 #include <media/DataSource.h>
-#include <media/MediaSource.h>
+#include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/AMessage.h>
 #include <media/stagefright/foundation/avc_utils.h>
@@ -209,7 +209,7 @@
     return valid;
 }
 
-class MP3Source : public MediaSource {
+class MP3Source : public MediaSourceBase {
 public:
     MP3Source(
             const sp<MetaData> &meta, const sp<DataSource> &source,
@@ -407,7 +407,7 @@
     return mInitCheck != OK ? 0 : 1;
 }
 
-sp<MediaSource> MP3Extractor::getTrack(size_t index) {
+MediaSourceBase *MP3Extractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
diff --git a/media/extractors/mp3/MP3Extractor.h b/media/extractors/mp3/MP3Extractor.h
index f0ab6b0..3b3387d 100644
--- a/media/extractors/mp3/MP3Extractor.h
+++ b/media/extractors/mp3/MP3Extractor.h
@@ -34,7 +34,7 @@
     MP3Extractor(const sp<DataSource> &source, const sp<AMessage> &meta);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual MediaSourceBase *getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 938bd5d..e88a464 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -31,7 +31,7 @@
 #include "ItemTable.h"
 #include "include/ESDS.h"
 
-#include <media/MediaSource.h>
+#include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -65,11 +65,10 @@
     kMaxAtomSize = 64 * 1024 * 1024,
 };
 
-class MPEG4Source : public MediaSource {
+class MPEG4Source : public MediaSourceBase {
 public:
     // Caller retains ownership of both "dataSource" and "sampleTable".
-    MPEG4Source(const sp<MPEG4Extractor> &owner,
-                const sp<MetaData> &format,
+    MPEG4Source(const sp<MetaData> &format,
                 const sp<DataSource> &dataSource,
                 int32_t timeScale,
                 const sp<SampleTable> &sampleTable,
@@ -88,14 +87,11 @@
     virtual bool supportNonblockingRead() { return true; }
     virtual status_t fragmentedRead(MediaBuffer **buffer, const ReadOptions *options = NULL);
 
-protected:
     virtual ~MPEG4Source();
 
 private:
     Mutex mLock;
 
-    // keep the MPEG4Extractor around, since we're referencing its data
-    sp<MPEG4Extractor> mOwner;
     sp<MetaData> mFormat;
     sp<DataSource> mDataSource;
     int32_t mTimescale;
@@ -3412,7 +3408,7 @@
     }
 }
 
-sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
+MediaSourceBase *MPEG4Extractor::getTrack(size_t index) {
     status_t err;
     if ((err = readMetaData()) != OK) {
         return NULL;
@@ -3488,10 +3484,11 @@
         }
     }
 
-    sp<MPEG4Source> source =  new MPEG4Source(this,
+    MPEG4Source *source =  new MPEG4Source(
             track->meta, mDataSource, track->timescale, track->sampleTable,
             mSidxEntries, trex, mMoofOffset, itemTable);
     if (source->init() != OK) {
+        delete source;
         return NULL;
     }
     return source;
@@ -3884,7 +3881,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG4Source::MPEG4Source(
-        const sp<MPEG4Extractor> &owner,
         const sp<MetaData> &format,
         const sp<DataSource> &dataSource,
         int32_t timeScale,
@@ -3893,8 +3889,7 @@
         const Trex *trex,
         off64_t firstMoofOffset,
         const sp<ItemTable> &itemTable)
-    : mOwner(owner),
-      mFormat(format),
+    : mFormat(format),
       mDataSource(dataSource),
       mTimescale(timeScale),
       mSampleTable(sampleTable),
diff --git a/media/extractors/mp4/MPEG4Extractor.h b/media/extractors/mp4/MPEG4Extractor.h
index 35c5321..e947b87 100644
--- a/media/extractors/mp4/MPEG4Extractor.h
+++ b/media/extractors/mp4/MPEG4Extractor.h
@@ -56,7 +56,7 @@
     explicit MPEG4Extractor(const sp<DataSource> &source, const char *mime = NULL);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual MediaSourceBase *getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.cpp b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
index c519caf..0978387 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.cpp
@@ -24,7 +24,7 @@
 #include "mpeg2ts/ESQueue.h"
 
 #include <media/DataSource.h>
-#include <media/MediaSource.h>
+#include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ABitReader.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
@@ -40,7 +40,7 @@
 
 namespace android {
 
-struct MPEG2PSExtractor::Track : public MediaSource {
+struct MPEG2PSExtractor::Track : public MediaSourceBase, public RefBase {
     Track(MPEG2PSExtractor *extractor,
           unsigned stream_id, unsigned stream_type);
 
@@ -72,8 +72,8 @@
     DISALLOW_EVIL_CONSTRUCTORS(Track);
 };
 
-struct MPEG2PSExtractor::WrappedTrack : public MediaSource {
-    WrappedTrack(const sp<MPEG2PSExtractor> &extractor, const sp<Track> &track);
+struct MPEG2PSExtractor::WrappedTrack : public MediaSourceBase {
+    WrappedTrack(MPEG2PSExtractor *extractor, const sp<Track> &track);
 
     virtual status_t start(MetaData *params);
     virtual status_t stop();
@@ -86,7 +86,7 @@
     virtual ~WrappedTrack();
 
 private:
-    sp<MPEG2PSExtractor> mExtractor;
+    MPEG2PSExtractor *mExtractor;
     sp<MPEG2PSExtractor::Track> mTrack;
 
     DISALLOW_EVIL_CONSTRUCTORS(WrappedTrack);
@@ -125,7 +125,7 @@
     return mTracks.size();
 }
 
-sp<MediaSource> MPEG2PSExtractor::getTrack(size_t index) {
+MediaSourceBase *MPEG2PSExtractor::getTrack(size_t index) {
     if (index >= mTracks.size()) {
         return NULL;
     }
@@ -723,7 +723,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 MPEG2PSExtractor::WrappedTrack::WrappedTrack(
-        const sp<MPEG2PSExtractor> &extractor, const sp<Track> &track)
+        MPEG2PSExtractor *extractor, const sp<Track> &track)
     : mExtractor(extractor),
       mTrack(track) {
 }
diff --git a/media/extractors/mpeg2/MPEG2PSExtractor.h b/media/extractors/mpeg2/MPEG2PSExtractor.h
index ab3ab05..f8a97ef 100644
--- a/media/extractors/mpeg2/MPEG2PSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2PSExtractor.h
@@ -34,7 +34,7 @@
     explicit MPEG2PSExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual MediaSourceBase *getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.cpp b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
index 5beaeda..b24e8db 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.cpp
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.cpp
@@ -24,7 +24,7 @@
 
 #include <media/DataSource.h>
 #include <media/IStreamSource.h>
-#include <media/MediaSource.h>
+#include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/ALooper.h>
@@ -49,11 +49,12 @@
 static const int kMaxDurationReadSize = 250000LL;
 static const int kMaxDurationRetry = 6;
 
-struct MPEG2TSSource : public MediaSource {
+struct MPEG2TSSource : public MediaSourceBase {
     MPEG2TSSource(
-            const sp<MPEG2TSExtractor> &extractor,
+            MPEG2TSExtractor *extractor,
             const sp<AnotherPacketSource> &impl,
             bool doesSeek);
+    virtual ~MPEG2TSSource();
 
     virtual status_t start(MetaData *params = NULL);
     virtual status_t stop();
@@ -63,7 +64,7 @@
             MediaBuffer **buffer, const ReadOptions *options = NULL);
 
 private:
-    sp<MPEG2TSExtractor> mExtractor;
+    MPEG2TSExtractor *mExtractor;
     sp<AnotherPacketSource> mImpl;
 
     // If there are both audio and video streams, only the video stream
@@ -74,7 +75,7 @@
 };
 
 MPEG2TSSource::MPEG2TSSource(
-        const sp<MPEG2TSExtractor> &extractor,
+        MPEG2TSExtractor *extractor,
         const sp<AnotherPacketSource> &impl,
         bool doesSeek)
     : mExtractor(extractor),
@@ -82,6 +83,9 @@
       mDoesSeek(doesSeek) {
 }
 
+MPEG2TSSource::~MPEG2TSSource() {
+}
+
 status_t MPEG2TSSource::start(MetaData *params) {
     return mImpl->start(params);
 }
@@ -129,7 +133,7 @@
     return mSourceImpls.size();
 }
 
-sp<MediaSource> MPEG2TSExtractor::getTrack(size_t index) {
+MediaSourceBase *MPEG2TSExtractor::getTrack(size_t index) {
     if (index >= mSourceImpls.size()) {
         return NULL;
     }
@@ -466,7 +470,7 @@
 }
 
 status_t MPEG2TSExtractor::seek(int64_t seekTimeUs,
-        const MediaSource::ReadOptions::SeekMode &seekMode) {
+        const MediaSourceBase::ReadOptions::SeekMode &seekMode) {
     if (mSeekSyncPoints == NULL || mSeekSyncPoints->isEmpty()) {
         ALOGW("No sync point to seek to.");
         // ... and therefore we have nothing useful to do here.
@@ -487,18 +491,18 @@
     }
 
     switch (seekMode) {
-        case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
+        case MediaSourceBase::ReadOptions::SEEK_NEXT_SYNC:
             if (index == mSeekSyncPoints->size()) {
                 ALOGW("Next sync not found; starting from the latest sync.");
                 --index;
             }
             break;
-        case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
-        case MediaSource::ReadOptions::SEEK_CLOSEST:
+        case MediaSourceBase::ReadOptions::SEEK_CLOSEST_SYNC:
+        case MediaSourceBase::ReadOptions::SEEK_CLOSEST:
             ALOGW("seekMode not supported: %d; falling back to PREVIOUS_SYNC",
                     seekMode);
             // fall-through
-        case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
+        case MediaSourceBase::ReadOptions::SEEK_PREVIOUS_SYNC:
             if (index == 0) {
                 ALOGW("Previous sync not found; starting from the earliest "
                         "sync.");
diff --git a/media/extractors/mpeg2/MPEG2TSExtractor.h b/media/extractors/mpeg2/MPEG2TSExtractor.h
index 55356bf..362f016 100644
--- a/media/extractors/mpeg2/MPEG2TSExtractor.h
+++ b/media/extractors/mpeg2/MPEG2TSExtractor.h
@@ -20,7 +20,7 @@
 
 #include <media/stagefright/foundation/ABase.h>
 #include <media/MediaExtractor.h>
-#include <media/MediaSource.h>
+#include <media/MediaSourceBase.h>
 #include <utils/threads.h>
 #include <utils/KeyedVector.h>
 #include <utils/Vector.h>
@@ -40,7 +40,7 @@
     explicit MPEG2TSExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual MediaSourceBase *getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/extractors/ogg/OggExtractor.cpp b/media/extractors/ogg/OggExtractor.cpp
index f42a6a8..f62ec47 100644
--- a/media/extractors/ogg/OggExtractor.cpp
+++ b/media/extractors/ogg/OggExtractor.cpp
@@ -22,7 +22,7 @@
 
 #include <cutils/properties.h>
 #include <media/DataSource.h>
-#include <media/MediaSource.h>
+#include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ABuffer.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/foundation/base64.h>
@@ -45,8 +45,8 @@
 
 namespace android {
 
-struct OggSource : public MediaSource {
-    explicit OggSource(const sp<OggExtractor> &extractor);
+struct OggSource : public MediaSourceBase {
+    explicit OggSource(OggExtractor *extractor);
 
     virtual sp<MetaData> getFormat();
 
@@ -60,7 +60,7 @@
     virtual ~OggSource();
 
 private:
-    sp<OggExtractor> mExtractor;
+    OggExtractor *mExtractor;
     bool mStarted;
 
     OggSource(const OggSource &);
@@ -224,7 +224,7 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-OggSource::OggSource(const sp<OggExtractor> &extractor)
+OggSource::OggSource(OggExtractor *extractor)
     : mExtractor(extractor),
       mStarted(false) {
 }
@@ -1348,7 +1348,7 @@
     return mInitCheck != OK ? 0 : 1;
 }
 
-sp<MediaSource> OggExtractor::getTrack(size_t index) {
+MediaSourceBase *OggExtractor::getTrack(size_t index) {
     if (index >= 1) {
         return NULL;
     }
diff --git a/media/extractors/ogg/OggExtractor.h b/media/extractors/ogg/OggExtractor.h
index 0f7fe5f..126428c 100644
--- a/media/extractors/ogg/OggExtractor.h
+++ b/media/extractors/ogg/OggExtractor.h
@@ -34,7 +34,7 @@
     explicit OggExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual MediaSourceBase *getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index 6c5f893..cf22c66 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -22,7 +22,7 @@
 
 #include <audio_utils/primitives.h>
 #include <media/DataSource.h>
-#include <media/MediaSource.h>
+#include <media/MediaSourceBase.h>
 #include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
@@ -55,7 +55,7 @@
     return ptr[1] << 8 | ptr[0];
 }
 
-struct WAVSource : public MediaSource {
+struct WAVSource : public MediaSourceBase {
     WAVSource(
             const sp<DataSource> &dataSource,
             const sp<MetaData> &meta,
@@ -120,7 +120,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-sp<MediaSource> WAVExtractor::getTrack(size_t index) {
+MediaSourceBase *WAVExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index > 0) {
         return NULL;
     }
@@ -564,8 +564,10 @@
         return NULL;
     }
 
-    sp<MediaExtractor> extractor = new WAVExtractor(source);
-    if (extractor->countTracks() == 0) {
+    MediaExtractor *extractor = new WAVExtractor(source);
+    int numTracks = extractor->countTracks();
+    delete extractor;
+    if (numTracks == 0) {
         return NULL;
     }
 
diff --git a/media/extractors/wav/WAVExtractor.h b/media/extractors/wav/WAVExtractor.h
index 98a2dfa..47c3c40 100644
--- a/media/extractors/wav/WAVExtractor.h
+++ b/media/extractors/wav/WAVExtractor.h
@@ -33,13 +33,12 @@
     explicit WAVExtractor(const sp<DataSource> &source);
 
     virtual size_t countTracks();
-    virtual sp<MediaSource> getTrack(size_t index);
+    virtual MediaSourceBase *getTrack(size_t index);
     virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
 
     virtual sp<MetaData> getMetaData();
     virtual const char * name() { return "WAVExtractor"; }
 
-protected:
     virtual ~WAVExtractor();
 
 private:
diff --git a/media/libmedia/include/media/DrmHal.h b/media/libmedia/include/media/DrmHal.h
index c18d845..ec3a9b3 100644
--- a/media/libmedia/include/media/DrmHal.h
+++ b/media/libmedia/include/media/DrmHal.h
@@ -97,10 +97,12 @@
                                               Vector<uint8_t> &wrappedKey);
 
     virtual status_t getSecureStops(List<Vector<uint8_t>> &secureStops);
+    virtual status_t getSecureStopIds(List<Vector<uint8_t>> &secureStopIds);
     virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop);
 
     virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
-    virtual status_t releaseAllSecureStops();
+    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid);
+    virtual status_t removeAllSecureStops();
 
     virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
             DrmPlugin::HdcpLevel *maxLevel) const;
diff --git a/media/libmedia/include/media/IDrm.h b/media/libmedia/include/media/IDrm.h
index 9266f99..994cade 100644
--- a/media/libmedia/include/media/IDrm.h
+++ b/media/libmedia/include/media/IDrm.h
@@ -74,10 +74,12 @@
                                               Vector<uint8_t> &wrappedKey) = 0;
 
     virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) = 0;
+    virtual status_t getSecureStopIds(List<Vector<uint8_t> > &secureStopIds) = 0;
     virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0;
 
     virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
-    virtual status_t releaseAllSecureStops() = 0;
+    virtual status_t removeSecureStop(Vector<uint8_t> const &ssid) = 0;
+    virtual status_t removeAllSecureStops() = 0;
 
     virtual status_t getHdcpLevels(DrmPlugin::HdcpLevel *connectedLevel,
             DrmPlugin::HdcpLevel *maxLevel)
diff --git a/media/libmediaextractor/Android.bp b/media/libmediaextractor/Android.bp
index 83fea39..984d4f1 100644
--- a/media/libmediaextractor/Android.bp
+++ b/media/libmediaextractor/Android.bp
@@ -26,6 +26,7 @@
         "DataSource.cpp",
         "MediaBuffer.cpp",
         "MediaBufferGroup.cpp",
+        "MediaSourceBase.cpp",
         "MediaSource.cpp",
         "MediaExtractor.cpp",
     ],
diff --git a/media/libmediaextractor/MediaSource.cpp b/media/libmediaextractor/MediaSource.cpp
index a5d41f7..5bbd3d8 100644
--- a/media/libmediaextractor/MediaSource.cpp
+++ b/media/libmediaextractor/MediaSource.cpp
@@ -25,45 +25,4 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-MediaSource::ReadOptions::ReadOptions() {
-    reset();
-}
-
-void MediaSource::ReadOptions::reset() {
-    mOptions = 0;
-    mSeekTimeUs = 0;
-    mNonBlocking = false;
-}
-
-void MediaSource::ReadOptions::setNonBlocking() {
-    mNonBlocking = true;
-}
-
-void MediaSource::ReadOptions::clearNonBlocking() {
-    mNonBlocking = false;
-}
-
-bool MediaSource::ReadOptions::getNonBlocking() const {
-    return mNonBlocking;
-}
-
-void MediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
-    mOptions |= kSeekTo_Option;
-    mSeekTimeUs = time_us;
-    mSeekMode = mode;
-}
-
-void MediaSource::ReadOptions::clearSeekTo() {
-    mOptions &= ~kSeekTo_Option;
-    mSeekTimeUs = 0;
-    mSeekMode = SEEK_CLOSEST_SYNC;
-}
-
-bool MediaSource::ReadOptions::getSeekTo(
-        int64_t *time_us, SeekMode *mode) const {
-    *time_us = mSeekTimeUs;
-    *mode = mSeekMode;
-    return (mOptions & kSeekTo_Option) != 0;
-}
-
 }  // namespace android
diff --git a/media/libmediaextractor/MediaSourceBase.cpp b/media/libmediaextractor/MediaSourceBase.cpp
new file mode 100644
index 0000000..6d45c90
--- /dev/null
+++ b/media/libmediaextractor/MediaSourceBase.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <media/MediaSourceBase.h>
+
+namespace android {
+
+MediaSourceBase::MediaSourceBase() {}
+
+MediaSourceBase::~MediaSourceBase() {}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MediaSourceBase::ReadOptions::ReadOptions() {
+    reset();
+}
+
+void MediaSourceBase::ReadOptions::reset() {
+    mOptions = 0;
+    mSeekTimeUs = 0;
+    mNonBlocking = false;
+}
+
+void MediaSourceBase::ReadOptions::setNonBlocking() {
+    mNonBlocking = true;
+}
+
+void MediaSourceBase::ReadOptions::clearNonBlocking() {
+    mNonBlocking = false;
+}
+
+bool MediaSourceBase::ReadOptions::getNonBlocking() const {
+    return mNonBlocking;
+}
+
+void MediaSourceBase::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
+    mOptions |= kSeekTo_Option;
+    mSeekTimeUs = time_us;
+    mSeekMode = mode;
+}
+
+void MediaSourceBase::ReadOptions::clearSeekTo() {
+    mOptions &= ~kSeekTo_Option;
+    mSeekTimeUs = 0;
+    mSeekMode = SEEK_CLOSEST_SYNC;
+}
+
+bool MediaSourceBase::ReadOptions::getSeekTo(
+        int64_t *time_us, SeekMode *mode) const {
+    *time_us = mSeekTimeUs;
+    *mode = mSeekMode;
+    return (mOptions & kSeekTo_Option) != 0;
+}
+
+}  // namespace android
diff --git a/media/libmediaextractor/include/media/MediaExtractor.h b/media/libmediaextractor/include/media/MediaExtractor.h
index 276cbed..15a5d8c 100644
--- a/media/libmediaextractor/include/media/MediaExtractor.h
+++ b/media/libmediaextractor/include/media/MediaExtractor.h
@@ -30,13 +30,28 @@
 class MetaData;
 class String8;
 struct AMessage;
-struct MediaSource;
+struct MediaSourceBase;
 typedef std::vector<uint8_t> HInterfaceToken;
 
-class MediaExtractor : public RefBase {
+
+class ExtractorAllocTracker {
 public:
+    ExtractorAllocTracker() {
+        ALOGD("extractor allocated: %p", this);
+    }
+    virtual ~ExtractorAllocTracker() {
+        ALOGD("extractor freed: %p", this);
+    }
+};
+
+
+class MediaExtractor
+// : public ExtractorAllocTracker
+{
+public:
+    virtual ~MediaExtractor();
     virtual size_t countTracks() = 0;
-    virtual sp<MediaSource> getTrack(size_t index) = 0;
+    virtual MediaSourceBase *getTrack(size_t index) = 0;
 
     enum GetTrackMetaDataFlags {
         kIncludeExtensiveMetaData = 1
@@ -112,7 +127,6 @@
 
 protected:
     MediaExtractor();
-    virtual ~MediaExtractor();
 
 private:
     MediaExtractor(const MediaExtractor &);
diff --git a/media/libmediaextractor/include/media/MediaSource.h b/media/libmediaextractor/include/media/MediaSource.h
index 3df9a0d..45070d6 100644
--- a/media/libmediaextractor/include/media/MediaSource.h
+++ b/media/libmediaextractor/include/media/MediaSource.h
@@ -24,105 +24,15 @@
 #include <media/stagefright/MetaData.h>
 #include <utils/RefBase.h>
 
+#include "media/MediaSourceBase.h"
+
 namespace android {
 
 class MediaBuffer;
 
-struct MediaSource : public virtual RefBase {
+struct MediaSource : public MediaSourceBase, public virtual RefBase {
     MediaSource();
 
-    // To be called before any other methods on this object, except
-    // getFormat().
-    virtual status_t start(MetaData *params = NULL) = 0;
-
-    // Any blocking read call returns immediately with a result of NO_INIT.
-    // It is an error to call any methods other than start after this call
-    // returns. Any buffers the object may be holding onto at the time of
-    // the stop() call are released.
-    // Also, it is imperative that any buffers output by this object and
-    // held onto by callers be released before a call to stop() !!!
-    virtual status_t stop() = 0;
-
-    // Returns the format of the data output by this media source.
-    virtual sp<MetaData> getFormat() = 0;
-
-    // Options that modify read() behaviour. The default is to
-    // a) not request a seek
-    // b) not be late, i.e. lateness_us = 0
-    struct ReadOptions {
-        enum SeekMode : int32_t {
-            SEEK_PREVIOUS_SYNC,
-            SEEK_NEXT_SYNC,
-            SEEK_CLOSEST_SYNC,
-            SEEK_CLOSEST,
-            SEEK_FRAME_INDEX,
-        };
-
-        ReadOptions();
-
-        // Reset everything back to defaults.
-        void reset();
-
-        void setSeekTo(int64_t time_us, SeekMode mode = SEEK_CLOSEST_SYNC);
-        void clearSeekTo();
-        bool getSeekTo(int64_t *time_us, SeekMode *mode) const;
-
-        void setNonBlocking();
-        void clearNonBlocking();
-        bool getNonBlocking() const;
-
-        // Used to clear all non-persistent options for multiple buffer reads.
-        void clearNonPersistent() {
-            clearSeekTo();
-        }
-
-    private:
-        enum Options {
-            kSeekTo_Option      = 1,
-        };
-
-        uint32_t mOptions;
-        int64_t mSeekTimeUs;
-        SeekMode mSeekMode;
-        bool mNonBlocking;
-    } __attribute__((packed)); // sent through Binder
-
-    // Returns a new buffer of data. Call blocks until a
-    // buffer is available, an error is encountered of the end of the stream
-    // is reached.
-    // End of stream is signalled by a result of ERROR_END_OF_STREAM.
-    // A result of INFO_FORMAT_CHANGED indicates that the format of this
-    // MediaSource has changed mid-stream, the client can continue reading
-    // but should be prepared for buffers of the new configuration.
-    virtual status_t read(
-            MediaBuffer **buffer, const ReadOptions *options = NULL) = 0;
-
-    // Causes this source to suspend pulling data from its upstream source
-    // until a subsequent read-with-seek. This is currently not supported
-    // as such by any source. E.g. MediaCodecSource does not suspend its
-    // upstream source, and instead discard upstream data while paused.
-    virtual status_t pause() {
-        return ERROR_UNSUPPORTED;
-    }
-
-    // The consumer of this media source requests the source stops sending
-    // buffers with timestamp larger than or equal to stopTimeUs. stopTimeUs
-    // must be in the same time base as the startTime passed in start(). If
-    // source does not support this request, ERROR_UNSUPPORTED will be returned.
-    // If stopTimeUs is invalid, BAD_VALUE will be returned. This could be
-    // called at any time even before source starts and it could be called
-    // multiple times. Setting stopTimeUs to be -1 will effectively cancel the stopTimeUs
-    // set previously. If stopTimeUs is larger than or equal to last buffer's timestamp,
-    // source will start to drop buffer when it gets a buffer with timestamp larger
-    // than or equal to stopTimeUs. If stopTimeUs is smaller than or equal to last
-    // buffer's timestamp, source will drop all the incoming buffers immediately.
-    // After setting stopTimeUs, source may still stop sending buffers with timestamp
-    // less than stopTimeUs if it is stopped by the consumer.
-    virtual status_t setStopTimeUs(int64_t /* stopTimeUs */) {
-        return ERROR_UNSUPPORTED;
-    }
-
-protected:
     virtual ~MediaSource();
 
 private:
diff --git a/media/libmediaextractor/include/media/MediaSourceBase.h b/media/libmediaextractor/include/media/MediaSourceBase.h
new file mode 100644
index 0000000..77d4fc9
--- /dev/null
+++ b/media/libmediaextractor/include/media/MediaSourceBase.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_SOURCE_BASE_H_
+
+#define MEDIA_SOURCE_BASE_H_
+
+#include <sys/types.h>
+
+#include <binder/IMemory.h>
+#include <binder/MemoryDealer.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+#include <utils/RefBase.h>
+#include <utils/Vector.h>
+
+namespace android {
+
+class MediaBuffer;
+
+class SourceBaseAllocTracker {
+public:
+    SourceBaseAllocTracker() {
+        ALOGD("sourcebase allocated: %p", this);
+    }
+    virtual ~SourceBaseAllocTracker() {
+        ALOGD("sourcebase freed: %p", this);
+    }
+};
+
+struct MediaSourceBase
+//    : public SourceBaseAllocTracker
+{
+    MediaSourceBase();
+
+    // To be called before any other methods on this object, except
+    // getFormat().
+    virtual status_t start(MetaData *params = NULL) = 0;
+
+    // Any blocking read call returns immediately with a result of NO_INIT.
+    // It is an error to call any methods other than start after this call
+    // returns. Any buffers the object may be holding onto at the time of
+    // the stop() call are released.
+    // Also, it is imperative that any buffers output by this object and
+    // held onto by callers be released before a call to stop() !!!
+    virtual status_t stop() = 0;
+
+    // Returns the format of the data output by this media source.
+    virtual sp<MetaData> getFormat() = 0;
+
+    // Options that modify read() behaviour. The default is to
+    // a) not request a seek
+    // b) not be late, i.e. lateness_us = 0
+    struct ReadOptions {
+        enum SeekMode : int32_t {
+            SEEK_PREVIOUS_SYNC,
+            SEEK_NEXT_SYNC,
+            SEEK_CLOSEST_SYNC,
+            SEEK_CLOSEST,
+            SEEK_FRAME_INDEX,
+        };
+
+        ReadOptions();
+
+        // Reset everything back to defaults.
+        void reset();
+
+        void setSeekTo(int64_t time_us, SeekMode mode = SEEK_CLOSEST_SYNC);
+        void clearSeekTo();
+        bool getSeekTo(int64_t *time_us, SeekMode *mode) const;
+
+        void setNonBlocking();
+        void clearNonBlocking();
+        bool getNonBlocking() const;
+
+        // Used to clear all non-persistent options for multiple buffer reads.
+        void clearNonPersistent() {
+            clearSeekTo();
+        }
+
+    private:
+        enum Options {
+            kSeekTo_Option      = 1,
+        };
+
+        uint32_t mOptions;
+        int64_t mSeekTimeUs;
+        SeekMode mSeekMode;
+        bool mNonBlocking;
+    } __attribute__((packed)); // sent through Binder
+
+    // Returns a new buffer of data. Call blocks until a
+    // buffer is available, an error is encountered of the end of the stream
+    // is reached.
+    // End of stream is signalled by a result of ERROR_END_OF_STREAM.
+    // A result of INFO_FORMAT_CHANGED indicates that the format of this
+    // MediaSource has changed mid-stream, the client can continue reading
+    // but should be prepared for buffers of the new configuration.
+    virtual status_t read(
+            MediaBuffer **buffer, const ReadOptions *options = NULL) = 0;
+
+    // Causes this source to suspend pulling data from its upstream source
+    // until a subsequent read-with-seek. This is currently not supported
+    // as such by any source. E.g. MediaCodecSource does not suspend its
+    // upstream source, and instead discard upstream data while paused.
+    virtual status_t pause() {
+        return ERROR_UNSUPPORTED;
+    }
+
+    // The consumer of this media source requests the source stops sending
+    // buffers with timestamp larger than or equal to stopTimeUs. stopTimeUs
+    // must be in the same time base as the startTime passed in start(). If
+    // source does not support this request, ERROR_UNSUPPORTED will be returned.
+    // If stopTimeUs is invalid, BAD_VALUE will be returned. This could be
+    // called at any time even before source starts and it could be called
+    // multiple times. Setting stopTimeUs to be -1 will effectively cancel the stopTimeUs
+    // set previously. If stopTimeUs is larger than or equal to last buffer's timestamp,
+    // source will start to drop buffer when it gets a buffer with timestamp larger
+    // than or equal to stopTimeUs. If stopTimeUs is smaller than or equal to last
+    // buffer's timestamp, source will drop all the incoming buffers immediately.
+    // After setting stopTimeUs, source may still stop sending buffers with timestamp
+    // less than stopTimeUs if it is stopped by the consumer.
+    virtual status_t setStopTimeUs(int64_t /* stopTimeUs */) {
+        return ERROR_UNSUPPORTED;
+    }
+
+    virtual ~MediaSourceBase();
+
+private:
+    MediaSourceBase(const MediaSourceBase &);
+    MediaSourceBase &operator=(const MediaSourceBase &);
+};
+
+}  // namespace android
+
+#endif  // MEDIA_SOURCE_BASE_H_
diff --git a/media/libstagefright/InterfaceUtils.cpp b/media/libstagefright/InterfaceUtils.cpp
index f174ba4..284e63b 100644
--- a/media/libstagefright/InterfaceUtils.cpp
+++ b/media/libstagefright/InterfaceUtils.cpp
@@ -19,7 +19,6 @@
 #include <media/stagefright/CallbackMediaSource.h>
 #include <media/stagefright/InterfaceUtils.h>
 #include <media/stagefright/RemoteDataSource.h>
-#include <media/stagefright/RemoteMediaExtractor.h>
 #include <media/stagefright/RemoteMediaSource.h>
 
 namespace android {
@@ -39,7 +38,7 @@
 }
 
 sp<IMediaExtractor> CreateIMediaExtractorFromMediaExtractor(
-        const sp<MediaExtractor> &extractor, const sp<RefBase> &plugin) {
+        MediaExtractor *extractor, const sp<RefBase> &plugin) {
     if (extractor == nullptr) {
         return nullptr;
     }
@@ -53,12 +52,13 @@
     return new CallbackMediaSource(source);
 }
 
-sp<IMediaSource> CreateIMediaSourceFromMediaSource(
-        const sp<MediaSource> &source, const sp<RefBase> &plugin) {
+sp<IMediaSource> CreateIMediaSourceFromMediaSourceBase(
+        const sp<RemoteMediaExtractor> &extractor,
+        MediaSourceBase *source, const sp<RefBase> &plugin) {
     if (source == nullptr) {
         return nullptr;
     }
-    return RemoteMediaSource::wrap(source, plugin);
+    return RemoteMediaSource::wrap(extractor, source, plugin);
 }
 
 }  // namespace android
diff --git a/media/libstagefright/RemoteMediaExtractor.cpp b/media/libstagefright/RemoteMediaExtractor.cpp
index 12654d9..43d33e5 100644
--- a/media/libstagefright/RemoteMediaExtractor.cpp
+++ b/media/libstagefright/RemoteMediaExtractor.cpp
@@ -37,7 +37,7 @@
 static const char *kExtractorFormat = "android.media.mediaextractor.fmt";
 
 RemoteMediaExtractor::RemoteMediaExtractor(
-        const sp<MediaExtractor> &extractor, const sp<RefBase> &plugin)
+        MediaExtractor *extractor, const sp<RefBase> &plugin)
     :mExtractor(extractor),
     mExtractorPlugin(plugin) {
 
@@ -67,7 +67,7 @@
 }
 
 RemoteMediaExtractor::~RemoteMediaExtractor() {
-    mExtractor = nullptr;
+    delete mExtractor;
     mExtractorPlugin = nullptr;
     // log the current record, provided it has some information worth recording
     if (MEDIA_LOG) {
@@ -89,9 +89,9 @@
 }
 
 sp<IMediaSource> RemoteMediaExtractor::getTrack(size_t index) {
-    sp<MediaSource> source = mExtractor->getTrack(index);
-    return (source.get() == nullptr)
-            ? nullptr : CreateIMediaSourceFromMediaSource(source, mExtractorPlugin);
+    MediaSourceBase *source = mExtractor->getTrack(index);
+    return (source == nullptr)
+            ? nullptr : CreateIMediaSourceFromMediaSourceBase(this, source, mExtractorPlugin);
 }
 
 sp<MetaData> RemoteMediaExtractor::getTrackMetaData(size_t index, uint32_t flags) {
@@ -139,8 +139,8 @@
 
 // static
 sp<IMediaExtractor> RemoteMediaExtractor::wrap(
-        const sp<MediaExtractor> &extractor, const sp<RefBase> &plugin) {
-    if (extractor.get() == nullptr) {
+        MediaExtractor *extractor, const sp<RefBase> &plugin) {
+    if (extractor == nullptr) {
         return nullptr;
     }
     return new RemoteMediaExtractor(extractor, plugin);
diff --git a/media/libstagefright/RemoteMediaSource.cpp b/media/libstagefright/RemoteMediaSource.cpp
index d97329c..6b48ce8 100644
--- a/media/libstagefright/RemoteMediaSource.cpp
+++ b/media/libstagefright/RemoteMediaSource.cpp
@@ -14,17 +14,22 @@
  * limitations under the License.
  */
 
+#include <media/stagefright/RemoteMediaExtractor.h>
 #include <media/stagefright/RemoteMediaSource.h>
 #include <media/IMediaSource.h>
 
 namespace android {
 
-RemoteMediaSource::RemoteMediaSource(const sp<MediaSource> &source, const sp<RefBase> &plugin)
-    :mSource(source),
-    mExtractorPlugin(plugin) {}
+RemoteMediaSource::RemoteMediaSource(
+        const sp<RemoteMediaExtractor> &extractor,
+        MediaSourceBase *source,
+        const sp<RefBase> &plugin)
+    : mExtractor(extractor),
+      mSource(source),
+      mExtractorPlugin(plugin) {}
 
 RemoteMediaSource::~RemoteMediaSource() {
-    mSource = nullptr;
+    delete mSource;
     mExtractorPlugin = nullptr;
 }
 
@@ -55,11 +60,13 @@
 ////////////////////////////////////////////////////////////////////////////////
 
 // static
-sp<IMediaSource> RemoteMediaSource::wrap(const sp<MediaSource> &source, const sp<RefBase> &plugin) {
-    if (source.get() == nullptr) {
+sp<IMediaSource> RemoteMediaSource::wrap(
+        const sp<RemoteMediaExtractor> &extractor,
+        MediaSourceBase *source, const sp<RefBase> &plugin) {
+    if (source == nullptr) {
         return nullptr;
     }
-    return new RemoteMediaSource(source, plugin);
+    return new RemoteMediaSource(extractor, source, plugin);
 }
 
 }  // namespace android
diff --git a/media/libstagefright/include/media/stagefright/InterfaceUtils.h b/media/libstagefright/include/media/stagefright/InterfaceUtils.h
index d449aec..ceeaf31 100644
--- a/media/libstagefright/include/media/stagefright/InterfaceUtils.h
+++ b/media/libstagefright/include/media/stagefright/InterfaceUtils.h
@@ -18,6 +18,11 @@
 #define INTERFACE_UTILS_H_
 
 #include <utils/RefBase.h>
+#include <media/MediaExtractor.h>
+#include <media/stagefright/RemoteMediaExtractor.h>
+#include <media/MediaSource.h>
+#include <media/IMediaExtractor.h>
+#include <media/IMediaSource.h>
 
 namespace android {
 
@@ -36,14 +41,15 @@
 
 // Creates an IMediaExtractor wrapper to the given MediaExtractor.
 sp<IMediaExtractor> CreateIMediaExtractorFromMediaExtractor(
-        const sp<MediaExtractor> &extractor, const sp<RefBase> &plugin);
+        MediaExtractor *extractor, const sp<RefBase> &plugin);
 
 // Creates a MediaSource which wraps the given IMediaSource object.
 sp<MediaSource> CreateMediaSourceFromIMediaSource(const sp<IMediaSource> &source);
 
 // Creates an IMediaSource wrapper to the given MediaSource.
-sp<IMediaSource> CreateIMediaSourceFromMediaSource(
-        const sp<MediaSource> &source, const sp<RefBase> &plugin);
+sp<IMediaSource> CreateIMediaSourceFromMediaSourceBase(
+        const sp<RemoteMediaExtractor> &extractor,
+        MediaSourceBase *source, const sp<RefBase> &plugin);
 
 }  // namespace android
 
diff --git a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
index bdbad7a..78f3a84 100644
--- a/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
+++ b/media/libstagefright/include/media/stagefright/RemoteMediaExtractor.h
@@ -28,7 +28,7 @@
 // IMediaExtractor wrapper to the MediaExtractor.
 class RemoteMediaExtractor : public BnMediaExtractor {
 public:
-    static sp<IMediaExtractor> wrap(const sp<MediaExtractor> &extractor, const sp<RefBase> &plugin);
+    static sp<IMediaExtractor> wrap(MediaExtractor *extractor, const sp<RefBase> &plugin);
 
     virtual ~RemoteMediaExtractor();
     virtual size_t countTracks();
@@ -44,12 +44,12 @@
     virtual void release();
 
 private:
-    sp<MediaExtractor> mExtractor;
+    MediaExtractor *mExtractor;
     sp<RefBase> mExtractorPlugin;
 
     MediaAnalyticsItem *mAnalyticsItem;
 
-    explicit RemoteMediaExtractor(const sp<MediaExtractor> &extractor, const sp<RefBase> &plugin);
+    explicit RemoteMediaExtractor(MediaExtractor *extractor, const sp<RefBase> &plugin);
 
     DISALLOW_EVIL_CONSTRUCTORS(RemoteMediaExtractor);
 };
diff --git a/media/libstagefright/include/media/stagefright/RemoteMediaSource.h b/media/libstagefright/include/media/stagefright/RemoteMediaSource.h
index cb222cc..d1afa6a 100644
--- a/media/libstagefright/include/media/stagefright/RemoteMediaSource.h
+++ b/media/libstagefright/include/media/stagefright/RemoteMediaSource.h
@@ -26,7 +26,10 @@
 // IMediaSrouce wrapper to the MediaSource.
 class RemoteMediaSource : public BnMediaSource {
 public:
-    static sp<IMediaSource> wrap(const sp<MediaSource> &source, const sp<RefBase> &plugin);
+    static sp<IMediaSource> wrap(
+            const sp<RemoteMediaExtractor> &extractor,
+            MediaSourceBase *source,
+            const sp<RefBase> &plugin);
     virtual ~RemoteMediaSource();
     virtual status_t start(MetaData *params = NULL);
     virtual status_t stop();
@@ -38,10 +41,14 @@
     virtual status_t setStopTimeUs(int64_t stopTimeUs);
 
 private:
-    sp<MediaSource> mSource;
+    sp<RemoteMediaExtractor> mExtractor;
+    MediaSourceBase *mSource;
     sp<RefBase> mExtractorPlugin;
 
-    explicit RemoteMediaSource(const sp<MediaSource> &source, const sp<RefBase> &plugin);
+    explicit RemoteMediaSource(
+            const sp<RemoteMediaExtractor> &extractor,
+            MediaSourceBase *source,
+            const sp<RefBase> &plugin);
 
     DISALLOW_EVIL_CONSTRUCTORS(RemoteMediaSource);
 };
diff --git a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
index 30e32ec..4144342 100644
--- a/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaController2Impl.java
@@ -53,10 +53,9 @@
     private static final boolean DEBUG = true; // TODO(jaewan): Change
 
     private final MediaController2 mInstance;
-
+    private final Context mContext;
     private final Object mLock = new Object();
 
-    private final Context mContext;
     private final MediaSession2CallbackStub mSessionCallbackStub;
     private final SessionToken2 mToken;
     private final ControllerCallback mCallback;
@@ -209,6 +208,10 @@
         return mCallbackExecutor;
     }
 
+    Context getContext() {
+      return mContext;
+    }
+
     @Override
     public SessionToken2 getSessionToken_impl() {
         return mToken;
@@ -606,7 +609,7 @@
                 return;
             }
             controller.onConnectionChangedNotLocked(
-                    sessionBinder, CommandGroup.fromBundle(commandGroup));
+                    sessionBinder, CommandGroup.fromBundle(controller.getContext(), commandGroup));
         }
 
         @Override
@@ -645,7 +648,8 @@
             }
             List<CommandButton> layout = new ArrayList<>();
             for (int i = 0; i < commandButtonlist.size(); i++) {
-                CommandButton button = CommandButton.fromBundle(commandButtonlist.get(i));
+                CommandButton button = CommandButton.fromBundle(
+                        browser.getContext(), commandButtonlist.get(i));
                 if (button != null) {
                     layout.add(button);
                 }
@@ -662,7 +666,7 @@
                 Log.w(TAG, "Don't fail silently here. Highly likely a bug");
                 return;
             }
-            Command command = Command.fromBundle(commandBundle);
+            Command command = Command.fromBundle(controller.getContext(), commandBundle);
             if (command == null) {
                 return;
             }
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
index 7c36739..5bb608d 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Impl.java
@@ -20,6 +20,8 @@
 import static android.media.SessionToken2.TYPE_SESSION;
 import static android.media.SessionToken2.TYPE_SESSION_SERVICE;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.Manifest.permission;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -520,6 +522,96 @@
         }
     }
 
+    public static final class CommandImpl implements CommandProvider {
+        private static final String KEY_COMMAND_CODE
+                = "android.media.media_session2.command.command_code";
+        private static final String KEY_COMMAND_CUSTOM_COMMAND
+                = "android.media.media_session2.command.custom_command";
+        private static final String KEY_COMMAND_EXTRA
+                = "android.media.media_session2.command.extra";
+
+        private final Command mInstance;
+        private final int mCommandCode;
+        // Nonnull if it's custom command
+        private final String mCustomCommand;
+        private final Bundle mExtra;
+
+        public CommandImpl(Command instance, int commandCode) {
+            mInstance = instance;
+            mCommandCode = commandCode;
+            mCustomCommand = null;
+            mExtra = null;
+        }
+
+        public CommandImpl(Command instance, @NonNull String action, @Nullable Bundle extra) {
+            if (action == null) {
+                throw new IllegalArgumentException("action shouldn't be null");
+            }
+            mInstance = instance;
+            mCommandCode = MediaSession2.COMMAND_CODE_CUSTOM;
+            mCustomCommand = action;
+            mExtra = extra;
+        }
+
+        public int getCommandCode_impl() {
+            return mCommandCode;
+        }
+
+        public @Nullable String getCustomCommand_impl() {
+            return mCustomCommand;
+        }
+
+        public @Nullable Bundle getExtra_impl() {
+            return mExtra;
+        }
+
+        /**
+         * @ 7return a new Bundle instance from the Command
+         */
+        public Bundle toBundle_impl() {
+            Bundle bundle = new Bundle();
+            bundle.putInt(KEY_COMMAND_CODE, mCommandCode);
+            bundle.putString(KEY_COMMAND_CUSTOM_COMMAND, mCustomCommand);
+            bundle.putBundle(KEY_COMMAND_EXTRA, mExtra);
+            return bundle;
+        }
+
+        /**
+         * @return a new Command instance from the Bundle
+         */
+        public static Command fromBundle_impl(Context context, Bundle command) {
+            int code = command.getInt(KEY_COMMAND_CODE);
+            if (code != MediaSession2.COMMAND_CODE_CUSTOM) {
+                return new Command(context, code);
+            } else {
+                String customCommand = command.getString(KEY_COMMAND_CUSTOM_COMMAND);
+                if (customCommand == null) {
+                    return null;
+                }
+                return new Command(context, customCommand, command.getBundle(KEY_COMMAND_EXTRA));
+            }
+        }
+
+        @Override
+        public boolean equals_impl(Object obj) {
+            if (!(obj instanceof CommandImpl)) {
+                return false;
+            }
+            CommandImpl other = (CommandImpl) obj;
+            // TODO(jaewan): Should we also compare contents in bundle?
+            //               It may not be possible if the bundle contains private class.
+            return mCommandCode == other.mCommandCode
+                    && TextUtils.equals(mCustomCommand, other.mCustomCommand);
+        }
+
+        @Override
+        public int hashCode_impl() {
+            final int prime = 31;
+            return ((mCustomCommand != null)
+                    ? mCustomCommand.hashCode() : 0) * prime + mCommandCode;
+        }
+    }
+
     public static class ControllerInfoImpl implements ControllerInfoProvider {
         private final ControllerInfo mInstance;
         private final int mUid;
diff --git a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
index 4fc69b9..4bb5f47 100644
--- a/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
+++ b/packages/MediaComponents/src/com/android/media/MediaSession2Stub.java
@@ -16,6 +16,7 @@
 
 package com.android.media;
 
+import android.content.Context;
 import android.media.MediaItem2;
 import android.media.MediaLibraryService2.BrowserRoot;
 import android.media.MediaLibraryService2.MediaLibrarySessionCallback;
@@ -92,7 +93,8 @@
     public void connect(String callingPackage, final IMediaSession2Callback callback)
             throws RuntimeException {
         final MediaSession2Impl sessionImpl = getSession();
-        final ControllerInfo request = new ControllerInfo(sessionImpl.getContext(),
+        final Context context = sessionImpl.getContext();
+        final ControllerInfo request = new ControllerInfo(context,
                 Binder.getCallingUid(), Binder.getCallingPid(), callingPackage, callback);
         sessionImpl.getCallbackExecutor().execute(() -> {
             final MediaSession2Impl session = mSession.get();
@@ -111,7 +113,7 @@
                 }
                 if (allowedCommands == null) {
                     // For trusted apps, send non-null allowed commands to keep connection.
-                    allowedCommands = new CommandGroup();
+                    allowedCommands = new CommandGroup(context);
                 }
             }
             if (DEBUG) {
@@ -178,7 +180,7 @@
                 return;
             }
             // TODO(jaewan): Sanity check.
-            Command command = new Command(commandCode);
+            Command command = new Command(session.getContext(), commandCode);
             boolean accepted = session.getCallback().onCommandRequest(controller, command);
             if (!accepted) {
                 // Don't run rejected command.
@@ -248,7 +250,7 @@
             if (session == null) {
                 return;
             }
-            final Command command = Command.fromBundle(commandBundle);
+            final Command command = Command.fromBundle(session.getContext(), commandBundle);
             session.getCallback().onCustomCommand(controller, command, args, receiver);
         });
     }
diff --git a/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java b/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java
index c91a89c..b2b7959 100644
--- a/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java
+++ b/packages/MediaComponents/src/com/android/media/SessionToken2Impl.java
@@ -152,7 +152,7 @@
         return mSessionBinder;
     }
 
-    public static SessionToken2 fromBundle(Context context, Bundle bundle) {
+    public static SessionToken2 fromBundle_impl(Context context, Bundle bundle) {
         if (bundle == null) {
             return null;
         }
diff --git a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
index b9d7612..0fc1ac1 100644
--- a/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
+++ b/packages/MediaComponents/src/com/android/media/update/ApiFactory.java
@@ -32,6 +32,7 @@
 import android.media.MediaMetadata2;
 import android.media.MediaPlayerInterface;
 import android.media.MediaSession2;
+import android.media.MediaSession2.Command;
 import android.media.MediaSession2.ControllerInfo;
 import android.media.MediaSession2.SessionCallback;
 import android.media.MediaSessionService2;
@@ -110,6 +111,20 @@
     }
 
     @Override
+    public MediaSession2Provider.CommandProvider createMediaSession2Command(Command instance,
+            int commandCode, String action, Bundle extra) {
+        if (action == null && extra == null) {
+            return new MediaSession2Impl.CommandImpl(instance, commandCode);
+        }
+        return new MediaSession2Impl.CommandImpl(instance, action, extra);
+    }
+
+    @Override
+    public Command fromBundle_MediaSession2Command(Context context, Bundle command) {
+        return MediaSession2Impl.CommandImpl.fromBundle_impl(context, command);
+    }
+
+    @Override
     public MediaSessionService2Provider createMediaSessionService2(
             MediaSessionService2 instance) {
         return new MediaSessionService2Impl(instance);
@@ -151,7 +166,7 @@
 
     @Override
     public SessionToken2 SessionToken2_fromBundle(Context context, Bundle bundle) {
-        return SessionToken2Impl.fromBundle(context, bundle);
+        return SessionToken2Impl.fromBundle_impl(context, bundle);
     }
 
     @Override
diff --git a/packages/MediaComponents/test/src/android/media/MediaController2Test.java b/packages/MediaComponents/test/src/android/media/MediaController2Test.java
index 9c5aa21..27dbaf8 100644
--- a/packages/MediaComponents/test/src/android/media/MediaController2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaController2Test.java
@@ -68,7 +68,7 @@
         // Create this test specific MediaSession2 to use our own Handler.
         mPlayer = new MockPlayer(1);
         mSession = new MediaSession2.Builder(mContext, mPlayer)
-                .setSessionCallback(sHandlerExecutor, new SessionCallback())
+                .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext))
                 .setId(TAG).build();
         mController = createController(mSession.getToken());
         TestServiceRegistry.getInstance().setHandler(sHandler);
@@ -256,12 +256,13 @@
     @Test
     public void testSendCustomCommand() throws InterruptedException {
         // TODO(jaewan): Need to revisit with the permission.
-        final Command testCommand = new Command(MediaSession2.COMMAND_CODE_PLAYBACK_PREPARE);
+        final Command testCommand =
+                new Command(mContext, MediaSession2.COMMAND_CODE_PLAYBACK_PREPARE);
         final Bundle testArgs = new Bundle();
         testArgs.putString("args", "testSendCustomAction");
 
         final CountDownLatch latch = new CountDownLatch(1);
-        final SessionCallback callback = new SessionCallback() {
+        final SessionCallback callback = new SessionCallback(mContext) {
             @Override
             public void onCustomCommand(ControllerInfo controller, Command customCommand,
                     Bundle args, ResultReceiver cb) {
@@ -291,7 +292,7 @@
 
     @Test
     public void testControllerCallback_sessionRejects() throws InterruptedException {
-        final MediaSession2.SessionCallback sessionCallback = new SessionCallback() {
+        final MediaSession2.SessionCallback sessionCallback = new SessionCallback(mContext) {
             @Override
             public MediaSession2.CommandGroup onConnect(ControllerInfo controller) {
                 return null;
@@ -357,7 +358,7 @@
             final MockPlayer player = new MockPlayer(0);
             sessionHandler.postAndSync(() -> {
                 mSession = new MediaSession2.Builder(mContext, mPlayer)
-                        .setSessionCallback(sHandlerExecutor, new SessionCallback())
+                        .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext))
                         .setId("testDeadlock").build();
             });
             final MediaController2 controller = createController(mSession.getToken());
@@ -545,7 +546,7 @@
             // Recreated session has different session stub, so previously created controller
             // shouldn't be available.
             mSession = new MediaSession2.Builder(mContext, mPlayer)
-                    .setSessionCallback(sHandlerExecutor, new SessionCallback())
+                    .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext))
                     .setId(id).build();
         });
         testNoInteraction();
diff --git a/packages/MediaComponents/test/src/android/media/MediaSession2Test.java b/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
index 6b10ccc..c5bcfff 100644
--- a/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
+++ b/packages/MediaComponents/test/src/android/media/MediaSession2Test.java
@@ -66,7 +66,7 @@
         super.setUp();
         mPlayer = new MockPlayer(0);
         mSession = new MediaSession2.Builder(mContext, mPlayer)
-                .setSessionCallback(sHandlerExecutor, new SessionCallback()).build();
+                .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext)).build();
     }
 
     @After
@@ -295,7 +295,8 @@
 
     @Test
     public void testSendCustomAction() throws InterruptedException {
-        final Command testCommand = new Command(MediaSession2.COMMAND_CODE_PLAYBACK_PREPARE);
+        final Command testCommand =
+                new Command(mContext, MediaSession2.COMMAND_CODE_PLAYBACK_PREPARE);
         final Bundle testArgs = new Bundle();
         testArgs.putString("args", "testSendCustomAction");
 
@@ -335,6 +336,10 @@
     }
 
     public class MockOnConnectCallback extends SessionCallback {
+        public MockOnConnectCallback() {
+            super(mContext);
+        }
+
         @Override
         public MediaSession2.CommandGroup onConnect(ControllerInfo controllerInfo) {
             if (Process.myUid() != controllerInfo.getUid()) {
@@ -351,6 +356,10 @@
     public class MockOnCommandCallback extends SessionCallback {
         public final ArrayList<MediaSession2.Command> commands = new ArrayList<>();
 
+        public MockOnCommandCallback() {
+            super(mContext);
+        }
+
         @Override
         public boolean onCommandRequest(ControllerInfo controllerInfo, MediaSession2.Command command) {
             assertEquals(mContext.getPackageName(), controllerInfo.getPackageName());
diff --git a/packages/MediaComponents/test/src/android/media/MediaSessionManager_MediaSession2.java b/packages/MediaComponents/test/src/android/media/MediaSessionManager_MediaSession2.java
index d0106fa..96ae8b7 100644
--- a/packages/MediaComponents/test/src/android/media/MediaSessionManager_MediaSession2.java
+++ b/packages/MediaComponents/test/src/android/media/MediaSessionManager_MediaSession2.java
@@ -60,7 +60,9 @@
         // per test thread differs across the {@link MediaSession2} with the same TAG.
         final MockPlayer player = new MockPlayer(1);
         mSession = new MediaSession2.Builder(mContext, player)
-                .setSessionCallback(sHandlerExecutor, new SessionCallback()).setId(TAG).build();
+                .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext))
+                .setId(TAG)
+                .build();
         ensureChangeInSession();
     }
 
@@ -109,7 +111,7 @@
         sHandler.postAndSync(() -> {
             mSession.close();
             mSession = new MediaSession2.Builder(mContext, new MockPlayer(0)).setId(TAG)
-                    .setSessionCallback(sHandlerExecutor, new SessionCallback() {
+                    .setSessionCallback(sHandlerExecutor, new SessionCallback(mContext) {
                         @Override
                         public MediaSession2.CommandGroup onConnect(ControllerInfo controller) {
                             // Reject all connection request.
diff --git a/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java b/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java
index c1187c2..6e1501a 100644
--- a/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java
+++ b/packages/MediaComponents/test/src/android/media/MockMediaLibraryService2.java
@@ -81,6 +81,10 @@
     }
 
     private class TestLibrarySessionCallback extends MediaLibrarySessionCallback {
+        public TestLibrarySessionCallback() {
+            super(MockMediaLibraryService2.this);
+        }
+
         @Override
         public CommandGroup onConnect(ControllerInfo controller) {
             if (Process.myUid() != controller.getUid()) {
diff --git a/packages/MediaComponents/test/src/android/media/MockMediaSessionService2.java b/packages/MediaComponents/test/src/android/media/MockMediaSessionService2.java
index 5c5c7d2..d85875e 100644
--- a/packages/MediaComponents/test/src/android/media/MockMediaSessionService2.java
+++ b/packages/MediaComponents/test/src/android/media/MockMediaSessionService2.java
@@ -91,6 +91,10 @@
     }
 
     private class MySessionCallback extends SessionCallback {
+        public MySessionCallback() {
+            super(MockMediaSessionService2.this);
+        }
+
         @Override
         public MediaSession2.CommandGroup onConnect(ControllerInfo controller) {
             if (Process.myUid() != controller.getUid()) {
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index b868fa6..f149f8a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -2400,6 +2400,8 @@
 
     Vector<camera3_stream_t*> streams;
     streams.setCapacity(config.num_streams);
+    std::vector<uint32_t> outBufSizes(mOutputStreams.size(), 0);
+
 
     if (mInputStream != NULL) {
         camera3_stream_t *inputStream;
@@ -2430,6 +2432,12 @@
             return INVALID_OPERATION;
         }
         streams.add(outputStream);
+
+        if (outputStream->format == HAL_PIXEL_FORMAT_BLOB &&
+                outputStream->data_space == HAL_DATASPACE_V0_JFIF) {
+            outBufSizes[i] = static_cast<uint32_t>(
+                    getJpegBufferSize(outputStream->width, outputStream->height));
+        }
     }
 
     config.streams = streams.editArray();
@@ -2438,7 +2446,7 @@
     // max_buffers, usage, priv fields.
 
     const camera_metadata_t *sessionBuffer = sessionParams.getAndLock();
-    res = mInterface->configureStreams(sessionBuffer, &config);
+    res = mInterface->configureStreams(sessionBuffer, &config, outBufSizes);
     sessionParams.unlock(sessionBuffer);
 
     if (res == BAD_VALUE) {
@@ -3494,7 +3502,7 @@
 }
 
 status_t Camera3Device::HalInterface::configureStreams(const camera_metadata_t *sessionParams,
-        camera3_stream_configuration *config) {
+        camera3_stream_configuration *config, const std::vector<uint32_t>& outputBufferSizes) {
     ATRACE_NAME("CameraHal::configureStreams");
     if (!valid()) return INVALID_OPERATION;
     status_t res = OK;
@@ -3535,6 +3543,7 @@
         dst3_2.dataSpace = mapToHidlDataspace(src->data_space);
         dst3_2.rotation = mapToStreamRotation((camera3_stream_rotation_t) src->rotation);
         dst3_4.v3_2 = dst3_2;
+        dst3_4.bufferSize = outputBufferSizes[i];
         if (src->physical_camera_id != nullptr) {
             dst3_4.physicalCameraId = src->physical_camera_id;
         }
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index bc97510..ccd9d7a 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -282,7 +282,8 @@
         status_t constructDefaultRequestSettings(camera3_request_template_t templateId,
                 /*out*/ camera_metadata_t **requestTemplate);
         status_t configureStreams(const camera_metadata_t *sessionParams,
-                /*inout*/ camera3_stream_configuration *config);
+                /*inout*/ camera3_stream_configuration *config,
+                const std::vector<uint32_t>& outputBufferSizes);
         status_t processCaptureRequest(camera3_capture_request_t *request);
         status_t processBatchCaptureRequests(
                 std::vector<camera3_capture_request_t*>& requests,