Merge "APM: Improve surround formats management, include MSD"
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index ddeb4ff..26bd96c 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -76,7 +76,11 @@
 
 // Convenience methods to obtain known clients.
 std::shared_ptr<Codec2Client> getClient(size_t index) {
-    return Codec2Client::CreateFromService(kClientNames[index]);
+    uint32_t serviceMask = ::android::base::GetUintProperty(
+            "debug.media.codec2", uint32_t(0));
+    return Codec2Client::CreateFromService(
+            kClientNames[index],
+            (serviceMask & (1 << index)) != 0);
 }
 
 ClientList getClientList() {
@@ -633,9 +637,13 @@
             Base::tryGetService(instanceName);
     if (!baseStore) {
         if (waitForService) {
-            ALOGE("Codec2.0 service inaccessible. Check the device manifest.");
+            ALOGW("Codec2.0 service \"%s\" inaccessible. "
+                  "Check the device manifest.",
+                  instanceName);
         } else {
-            ALOGW("Codec2.0 service not available right now. Try again later.");
+            ALOGD("Codec2.0 service \"%s\" unavailable right now. "
+                  "Try again later.",
+                  instanceName);
         }
         return nullptr;
     }
diff --git a/media/codec2/hidl/services/Android.bp b/media/codec2/hidl/services/Android.bp
index 965971e..216525e 100644
--- a/media/codec2/hidl/services/Android.bp
+++ b/media/codec2/hidl/services/Android.bp
@@ -37,58 +37,3 @@
     compile_multilib: "32",
 }
 
-cc_library_shared {
-    name: "libcodec2_serviceregistrant",
-    // need vendor version for update packaging, system version may have more dependencies
-    vendor_available: true,
-    srcs: [
-        "C2SoftwareCodecServiceRegistrant.cpp",
-    ],
-
-    header_libs: [
-        "libmedia_headers",
-    ],
-
-    shared_libs: [
-        "android.hardware.media.c2@1.0",
-        "libcodec2_hidl@1.0",
-        "libcodec2_vndk",
-        "liblog",
-        "libutils",
-    ],
-
-    // Codecs
-    runtime_libs: [
-        "libcodec2_soft_avcdec",
-        "libcodec2_soft_avcenc",
-        "libcodec2_soft_aacdec",
-        "libcodec2_soft_aacenc",
-        "libcodec2_soft_amrnbdec",
-        "libcodec2_soft_amrnbenc",
-        "libcodec2_soft_amrwbdec",
-        "libcodec2_soft_amrwbenc",
-        "libcodec2_soft_hevcdec",
-        "libcodec2_soft_g711alawdec",
-        "libcodec2_soft_g711mlawdec",
-        "libcodec2_soft_mpeg2dec",
-        "libcodec2_soft_h263dec",
-        "libcodec2_soft_h263enc",
-        "libcodec2_soft_mpeg4dec",
-        "libcodec2_soft_mpeg4enc",
-        "libcodec2_soft_mp3dec",
-        "libcodec2_soft_vorbisdec",
-        "libcodec2_soft_opusdec",
-        "libcodec2_soft_vp8dec",
-        "libcodec2_soft_vp9dec",
-        "libcodec2_soft_vp8enc",
-        "libcodec2_soft_vp9enc",
-        "libcodec2_soft_rawdec",
-        "libcodec2_soft_flacdec",
-        "libcodec2_soft_flacenc",
-        "libcodec2_soft_gsmdec",
-        "libcodec2_soft_xaacdec",
-    ],
-
-    compile_multilib: "32",
-}
-
diff --git a/media/codec2/vndk/C2PlatformStorePluginLoader.cpp b/media/codec2/vndk/C2PlatformStorePluginLoader.cpp
index 7a460f4..4c330e5 100644
--- a/media/codec2/vndk/C2PlatformStorePluginLoader.cpp
+++ b/media/codec2/vndk/C2PlatformStorePluginLoader.cpp
@@ -26,6 +26,12 @@
 /* static */ android::Mutex C2PlatformStorePluginLoader::sMutex;
 /* static */ std::unique_ptr<C2PlatformStorePluginLoader> C2PlatformStorePluginLoader::sInstance;
 
+namespace /* unnamed */ {
+
+constexpr const char kStorePluginPath[] = "libc2plugin_store.so";
+
+}  // unnamed
+
 C2PlatformStorePluginLoader::C2PlatformStorePluginLoader(const char *libPath)
     : mCreateBlockPool(nullptr) {
     mLibHandle = dlopen(libPath, RTLD_NOW | RTLD_NODELETE);
@@ -89,7 +95,7 @@
     android::Mutex::Autolock _l(sMutex);
     if (!sInstance) {
         ALOGV("Loading library");
-        sInstance.reset(new C2PlatformStorePluginLoader("libstagefright_ccodec_ext.so"));
+        sInstance.reset(new C2PlatformStorePluginLoader(kStorePluginPath));
     }
     return sInstance;
 }
diff --git a/media/codec2/vndk/C2Store.cpp b/media/codec2/vndk/C2Store.cpp
index 33019ed..2d4e19e 100644
--- a/media/codec2/vndk/C2Store.cpp
+++ b/media/codec2/vndk/C2Store.cpp
@@ -798,65 +798,65 @@
         mComponentsList.emplace_back(alias);
     };
     // TODO: move this also into a .so so it can be updated
-    emplace("c2.android.avc.decoder", "libstagefright_soft_c2avcdec.so");
-    emplace("c2.android.avc.encoder", "libstagefright_soft_c2avcenc.so");
-    emplace("c2.android.aac.decoder", "libstagefright_soft_c2aacdec.so");
-    emplace("c2.android.aac.encoder", "libstagefright_soft_c2aacenc.so");
-    emplace("c2.android.amrnb.decoder", "libstagefright_soft_c2amrnbdec.so");
-    emplace("c2.android.amrnb.encoder", "libstagefright_soft_c2amrnbenc.so");
-    emplace("c2.android.amrwb.decoder", "libstagefright_soft_c2amrwbdec.so");
-    emplace("c2.android.amrwb.encoder", "libstagefright_soft_c2amrwbenc.so");
-    emplace("c2.android.hevc.decoder", "libstagefright_soft_c2hevcdec.so");
-    emplace("c2.android.g711.alaw.decoder", "libstagefright_soft_c2g711alawdec.so");
-    emplace("c2.android.g711.mlaw.decoder", "libstagefright_soft_c2g711mlawdec.so");
-    emplace("c2.android.mpeg2.decoder", "libstagefright_soft_c2mpeg2dec.so");
-    emplace("c2.android.h263.decoder", "libstagefright_soft_c2h263dec.so");
-    emplace("c2.android.h263.encoder", "libstagefright_soft_c2h263enc.so");
-    emplace("c2.android.mpeg4.decoder", "libstagefright_soft_c2mpeg4dec.so");
-    emplace("c2.android.mpeg4.encoder", "libstagefright_soft_c2mpeg4enc.so");
-    emplace("c2.android.mp3.decoder", "libstagefright_soft_c2mp3dec.so");
-    emplace("c2.android.vorbis.decoder", "libstagefright_soft_c2vorbisdec.so");
-    emplace("c2.android.opus.decoder", "libstagefright_soft_c2opusdec.so");
-    emplace("c2.android.vp8.decoder", "libstagefright_soft_c2vp8dec.so");
-    emplace("c2.android.vp9.decoder", "libstagefright_soft_c2vp9dec.so");
-    emplace("c2.android.vp8.encoder", "libstagefright_soft_c2vp8enc.so");
-    emplace("c2.android.vp9.encoder", "libstagefright_soft_c2vp9enc.so");
-    emplace("c2.android.raw.decoder", "libstagefright_soft_c2rawdec.so");
-    emplace("c2.android.flac.decoder", "libstagefright_soft_c2flacdec.so");
-    emplace("c2.android.flac.encoder", "libstagefright_soft_c2flacenc.so");
-    emplace("c2.android.gsm.decoder", "libstagefright_soft_c2gsmdec.so");
-    emplace("c2.android.xaac.decoder", "libstagefright_soft_c2xaacdec.so");
+    emplace("c2.android.avc.decoder", "libcodec2_soft_avcdec.so");
+    emplace("c2.android.avc.encoder", "libcodec2_soft_avcenc.so");
+    emplace("c2.android.aac.decoder", "libcodec2_soft_aacdec.so");
+    emplace("c2.android.aac.encoder", "libcodec2_soft_aacenc.so");
+    emplace("c2.android.amrnb.decoder", "libcodec2_soft_amrnbdec.so");
+    emplace("c2.android.amrnb.encoder", "libcodec2_soft_amrnbenc.so");
+    emplace("c2.android.amrwb.decoder", "libcodec2_soft_amrwbdec.so");
+    emplace("c2.android.amrwb.encoder", "libcodec2_soft_amrwbenc.so");
+    emplace("c2.android.hevc.decoder", "libcodec2_soft_hevcdec.so");
+    emplace("c2.android.g711.alaw.decoder", "libcodec2_soft_g711alawdec.so");
+    emplace("c2.android.g711.mlaw.decoder", "libcodec2_soft_g711mlawdec.so");
+    emplace("c2.android.mpeg2.decoder", "libcodec2_soft_mpeg2dec.so");
+    emplace("c2.android.h263.decoder", "libcodec2_soft_h263dec.so");
+    emplace("c2.android.h263.encoder", "libcodec2_soft_h263enc.so");
+    emplace("c2.android.mpeg4.decoder", "libcodec2_soft_mpeg4dec.so");
+    emplace("c2.android.mpeg4.encoder", "libcodec2_soft_mpeg4enc.so");
+    emplace("c2.android.mp3.decoder", "libcodec2_soft_mp3dec.so");
+    emplace("c2.android.vorbis.decoder", "libcodec2_soft_vorbisdec.so");
+    emplace("c2.android.opus.decoder", "libcodec2_soft_opusdec.so");
+    emplace("c2.android.vp8.decoder", "libcodec2_soft_vp8dec.so");
+    emplace("c2.android.vp9.decoder", "libcodec2_soft_vp9dec.so");
+    emplace("c2.android.vp8.encoder", "libcodec2_soft_vp8enc.so");
+    emplace("c2.android.vp9.encoder", "libcodec2_soft_vp9enc.so");
+    emplace("c2.android.raw.decoder", "libcodec2_soft_rawdec.so");
+    emplace("c2.android.flac.decoder", "libcodec2_soft_flacdec.so");
+    emplace("c2.android.flac.encoder", "libcodec2_soft_flacenc.so");
+    emplace("c2.android.gsm.decoder", "libcodec2_soft_gsmdec.so");
+    emplace("c2.android.xaac.decoder", "libcodec2_soft_xaacdec.so");
 
     // "Aliases"
     // TODO: use aliases proper from C2Component::Traits
-    emplace("OMX.google.h264.decoder", "libstagefright_soft_c2avcdec.so");
-    emplace("OMX.google.h264.encoder", "libstagefright_soft_c2avcenc.so");
-    emplace("OMX.google.aac.decoder", "libstagefright_soft_c2aacdec.so");
-    emplace("OMX.google.aac.encoder", "libstagefright_soft_c2aacenc.so");
-    emplace("OMX.google.amrnb.decoder", "libstagefright_soft_c2amrnbdec.so");
-    emplace("OMX.google.amrnb.encoder", "libstagefright_soft_c2amrnbenc.so");
-    emplace("OMX.google.amrwb.decoder", "libstagefright_soft_c2amrwbdec.so");
-    emplace("OMX.google.amrwb.encoder", "libstagefright_soft_c2amrwbenc.so");
-    emplace("OMX.google.hevc.decoder", "libstagefright_soft_c2hevcdec.so");
-    emplace("OMX.google.g711.alaw.decoder", "libstagefright_soft_c2g711alawdec.so");
-    emplace("OMX.google.g711.mlaw.decoder", "libstagefright_soft_c2g711mlawdec.so");
-    emplace("OMX.google.mpeg2.decoder", "libstagefright_soft_c2mpeg2dec.so");
-    emplace("OMX.google.h263.decoder", "libstagefright_soft_c2h263dec.so");
-    emplace("OMX.google.h263.encoder", "libstagefright_soft_c2h263enc.so");
-    emplace("OMX.google.mpeg4.decoder", "libstagefright_soft_c2mpeg4dec.so");
-    emplace("OMX.google.mpeg4.encoder", "libstagefright_soft_c2mpeg4enc.so");
-    emplace("OMX.google.mp3.decoder", "libstagefright_soft_c2mp3dec.so");
-    emplace("OMX.google.vorbis.decoder", "libstagefright_soft_c2vorbisdec.so");
-    emplace("OMX.google.opus.decoder", "libstagefright_soft_c2opusdec.so");
-    emplace("OMX.google.vp8.decoder", "libstagefright_soft_c2vp8dec.so");
-    emplace("OMX.google.vp9.decoder", "libstagefright_soft_c2vp9dec.so");
-    emplace("OMX.google.vp8.encoder", "libstagefright_soft_c2vp8enc.so");
-    emplace("OMX.google.vp9.encoder", "libstagefright_soft_c2vp9enc.so");
-    emplace("OMX.google.raw.decoder", "libstagefright_soft_c2rawdec.so");
-    emplace("OMX.google.flac.decoder", "libstagefright_soft_c2flacdec.so");
-    emplace("OMX.google.flac.encoder", "libstagefright_soft_c2flacenc.so");
-    emplace("OMX.google.gsm.decoder", "libstagefright_soft_c2gsmdec.so");
-    emplace("OMX.google.xaac.decoder", "libstagefright_soft_c2xaacdec.so");
+    emplace("OMX.google.h264.decoder", "libcodec2_soft_avcdec.so");
+    emplace("OMX.google.h264.encoder", "libcodec2_soft_avcenc.so");
+    emplace("OMX.google.aac.decoder", "libcodec2_soft_aacdec.so");
+    emplace("OMX.google.aac.encoder", "libcodec2_soft_aacenc.so");
+    emplace("OMX.google.amrnb.decoder", "libcodec2_soft_amrnbdec.so");
+    emplace("OMX.google.amrnb.encoder", "libcodec2_soft_amrnbenc.so");
+    emplace("OMX.google.amrwb.decoder", "libcodec2_soft_amrwbdec.so");
+    emplace("OMX.google.amrwb.encoder", "libcodec2_soft_amrwbenc.so");
+    emplace("OMX.google.hevc.decoder", "libcodec2_soft_hevcdec.so");
+    emplace("OMX.google.g711.alaw.decoder", "libcodec2_soft_g711alawdec.so");
+    emplace("OMX.google.g711.mlaw.decoder", "libcodec2_soft_g711mlawdec.so");
+    emplace("OMX.google.mpeg2.decoder", "libcodec2_soft_mpeg2dec.so");
+    emplace("OMX.google.h263.decoder", "libcodec2_soft_h263dec.so");
+    emplace("OMX.google.h263.encoder", "libcodec2_soft_h263enc.so");
+    emplace("OMX.google.mpeg4.decoder", "libcodec2_soft_mpeg4dec.so");
+    emplace("OMX.google.mpeg4.encoder", "libcodec2_soft_mpeg4enc.so");
+    emplace("OMX.google.mp3.decoder", "libcodec2_soft_mp3dec.so");
+    emplace("OMX.google.vorbis.decoder", "libcodec2_soft_vorbisdec.so");
+    emplace("OMX.google.opus.decoder", "libcodec2_soft_opusdec.so");
+    emplace("OMX.google.vp8.decoder", "libcodec2_soft_vp8dec.so");
+    emplace("OMX.google.vp9.decoder", "libcodec2_soft_vp9dec.so");
+    emplace("OMX.google.vp8.encoder", "libcodec2_soft_vp8enc.so");
+    emplace("OMX.google.vp9.encoder", "libcodec2_soft_vp9enc.so");
+    emplace("OMX.google.raw.decoder", "libcodec2_soft_rawdec.so");
+    emplace("OMX.google.flac.decoder", "libcodec2_soft_flacdec.so");
+    emplace("OMX.google.flac.encoder", "libcodec2_soft_flacenc.so");
+    emplace("OMX.google.gsm.decoder", "libcodec2_soft_gsmdec.so");
+    emplace("OMX.google.xaac.decoder", "libcodec2_soft_xaacdec.so");
 }
 
 c2_status_t C2PlatformComponentStore::copyBuffer(
diff --git a/media/extractors/aac/AACExtractor.cpp b/media/extractors/aac/AACExtractor.cpp
index f278107..9384ebf 100644
--- a/media/extractors/aac/AACExtractor.cpp
+++ b/media/extractors/aac/AACExtractor.cpp
@@ -31,7 +31,7 @@
 
 namespace android {
 
-class AACSource : public MediaTrackHelperV2 {
+class AACSource : public MediaTrackHelperV3 {
 public:
     AACSource(
             DataSourceHelper *source,
@@ -45,7 +45,7 @@
     virtual media_status_t getFormat(AMediaFormat*);
 
     virtual media_status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
 protected:
     virtual ~AACSource();
@@ -58,7 +58,6 @@
     off64_t mOffset;
     int64_t mCurrentTimeUs;
     bool mStarted;
-    MediaBufferGroup *mGroup;
 
     Vector<uint64_t> mOffsetVector;
     int64_t mFrameDurationUs;
@@ -196,7 +195,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaTrackHelperV2 *AACExtractor::getTrack(size_t index) {
+MediaTrackHelperV3 *AACExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
@@ -227,7 +226,6 @@
       mOffset(0),
       mCurrentTimeUs(0),
       mStarted(false),
-      mGroup(NULL),
       mOffsetVector(offset_vector),
       mFrameDurationUs(frame_duration_us) {
 }
@@ -248,8 +246,7 @@
     }
 
     mCurrentTimeUs = 0;
-    mGroup = new MediaBufferGroup;
-    mGroup->add_buffer(MediaBufferBase::Create(kMaxFrameSize));
+    mBufferGroup->add_buffer(kMaxFrameSize);
     mStarted = true;
 
     return AMEDIA_OK;
@@ -258,9 +255,6 @@
 media_status_t AACSource::stop() {
     CHECK(mStarted);
 
-    delete mGroup;
-    mGroup = NULL;
-
     mStarted = false;
     return AMEDIA_OK;
 }
@@ -270,7 +264,7 @@
 }
 
 media_status_t AACSource::read(
-        MediaBufferBase **out, const ReadOptions *options) {
+        MediaBufferHelperV3 **out, const ReadOptions *options) {
     *out = NULL;
 
     int64_t seekTimeUs;
@@ -293,8 +287,8 @@
         return AMEDIA_ERROR_END_OF_STREAM;
     }
 
-    MediaBufferBase *buffer;
-    status_t err = mGroup->acquire_buffer(&buffer);
+    MediaBufferHelperV3 *buffer;
+    status_t err = mBufferGroup->acquire_buffer(&buffer);
     if (err != OK) {
         return AMEDIA_ERROR_UNKNOWN;
     }
@@ -309,8 +303,9 @@
     }
 
     buffer->set_range(0, frameSizeWithoutHeader);
-    buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
-    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+    AMediaFormat *meta = buffer->meta_data();
+    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, mCurrentTimeUs);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
     mOffset += frameSize;
     mCurrentTimeUs += mFrameDurationUs;
@@ -321,14 +316,14 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-static CMediaExtractorV2* CreateExtractor(
+static CMediaExtractorV3* CreateExtractor(
         CDataSource *source,
         void *meta) {
     off64_t offset = *static_cast<off64_t*>(meta);
-    return wrapV2(new AACExtractor(new DataSourceHelper(source), offset));
+    return wrapV3(new AACExtractor(new DataSourceHelper(source), offset));
 }
 
-static CreatorFuncV2 Sniff(
+static CreatorFuncV3 Sniff(
         CDataSource *source, float *confidence, void **meta,
         FreeMetaFunc *freeMeta) {
     off64_t pos = 0;
@@ -388,11 +383,11 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION_CURRENT,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("4fd80eae-03d2-4d72-9eb9-48fa6bb54613"),
         1, // version
         "AAC Extractor",
-        { .v2 = Sniff }
+        { .v3 = Sniff }
     };
 }
 
diff --git a/media/extractors/aac/AACExtractor.h b/media/extractors/aac/AACExtractor.h
index 3b11f95..be33bf5 100644
--- a/media/extractors/aac/AACExtractor.h
+++ b/media/extractors/aac/AACExtractor.h
@@ -29,12 +29,12 @@
 struct AMessage;
 class String8;
 
-class AACExtractor : public MediaExtractorPluginHelperV2 {
+class AACExtractor : public MediaExtractorPluginHelperV3 {
 public:
     AACExtractor(DataSourceHelper *source, off64_t offset);
 
     virtual size_t countTracks();
-    virtual MediaTrackHelperV2 *getTrack(size_t index);
+    virtual MediaTrackHelperV3 *getTrack(size_t index);
     virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
     virtual media_status_t getMetaData(AMediaFormat *meta);
diff --git a/media/extractors/aac/Android.bp b/media/extractors/aac/Android.bp
index a5e91bb..a58167a 100644
--- a/media/extractors/aac/Android.bp
+++ b/media/extractors/aac/Android.bp
@@ -8,7 +8,6 @@
 
     shared_libs: [
         "liblog",
-        "libmediaextractor",
         "libmediandk",
     ],
 
diff --git a/media/extractors/amr/AMRExtractor.cpp b/media/extractors/amr/AMRExtractor.cpp
index 511b14d..7fd2a41 100644
--- a/media/extractors/amr/AMRExtractor.cpp
+++ b/media/extractors/amr/AMRExtractor.cpp
@@ -29,7 +29,7 @@
 
 namespace android {
 
-class AMRSource : public MediaTrackHelperV2 {
+class AMRSource : public MediaTrackHelperV3 {
 public:
     AMRSource(
             DataSourceHelper *source,
@@ -44,7 +44,7 @@
     virtual media_status_t getFormat(AMediaFormat *);
 
     virtual media_status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
 protected:
     virtual ~AMRSource();
@@ -209,7 +209,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaTrackHelperV2 *AMRExtractor::getTrack(size_t index) {
+MediaTrackHelperV3 *AMRExtractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
@@ -255,8 +255,7 @@
 
     mOffset = mIsWide ? 9 : 6;
     mCurrentTimeUs = 0;
-    mGroup = new MediaBufferGroup;
-    mGroup->add_buffer(MediaBufferBase::Create(128));
+    mBufferGroup->add_buffer(128);
     mStarted = true;
 
     return AMEDIA_OK;
@@ -265,9 +264,6 @@
 media_status_t AMRSource::stop() {
     CHECK(mStarted);
 
-    delete mGroup;
-    mGroup = NULL;
-
     mStarted = false;
     return AMEDIA_OK;
 }
@@ -277,7 +273,7 @@
 }
 
 media_status_t AMRSource::read(
-        MediaBufferBase **out, const ReadOptions *options) {
+        MediaBufferHelperV3 **out, const ReadOptions *options) {
     *out = NULL;
 
     int64_t seekTimeUs;
@@ -326,8 +322,8 @@
         return AMEDIA_ERROR_MALFORMED;
     }
 
-    MediaBufferBase *buffer;
-    status_t err = mGroup->acquire_buffer(&buffer);
+    MediaBufferHelperV3 *buffer;
+    status_t err = mBufferGroup->acquire_buffer(&buffer);
     if (err != OK) {
         return AMEDIA_ERROR_UNKNOWN;
     }
@@ -348,8 +344,9 @@
     }
 
     buffer->set_range(0, frameSize);
-    buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
-    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+    AMediaFormat *meta = buffer->meta_data();
+    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, mCurrentTimeUs);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
     mOffset += frameSize;
     mCurrentTimeUs += 20000;  // Each frame is 20ms
@@ -366,22 +363,22 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION_CURRENT,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("c86639c9-2f31-40ac-a715-fa01b4493aaf"),
         1,
         "AMR Extractor",
         {
-           .v2 = [](
+           .v3 = [](
                     CDataSource *source,
                     float *confidence,
                     void **,
-                    FreeMetaFunc *) -> CreatorFuncV2 {
+                    FreeMetaFunc *) -> CreatorFuncV3 {
                 DataSourceHelper helper(source);
                 if (SniffAMR(&helper, nullptr, confidence)) {
                     return [](
                             CDataSource *source,
-                            void *) -> CMediaExtractorV2* {
-                        return wrapV2(new AMRExtractor(new DataSourceHelper(source)));};
+                            void *) -> CMediaExtractorV3* {
+                        return wrapV3(new AMRExtractor(new DataSourceHelper(source)));};
                 }
                 return NULL;
             }
diff --git a/media/extractors/amr/AMRExtractor.h b/media/extractors/amr/AMRExtractor.h
index 44b2cbd..b50ce81 100644
--- a/media/extractors/amr/AMRExtractor.h
+++ b/media/extractors/amr/AMRExtractor.h
@@ -29,12 +29,12 @@
 class String8;
 #define OFFSET_TABLE_LEN    300
 
-class AMRExtractor : public MediaExtractorPluginHelperV2 {
+class AMRExtractor : public MediaExtractorPluginHelperV3 {
 public:
     explicit AMRExtractor(DataSourceHelper *source);
 
     virtual size_t countTracks();
-    virtual MediaTrackHelperV2 *getTrack(size_t index);
+    virtual MediaTrackHelperV3 *getTrack(size_t index);
     virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
     virtual media_status_t getMetaData(AMediaFormat *meta);
diff --git a/media/extractors/amr/Android.bp b/media/extractors/amr/Android.bp
index 0791fa3..4bd933d 100644
--- a/media/extractors/amr/Android.bp
+++ b/media/extractors/amr/Android.bp
@@ -8,7 +8,6 @@
 
     shared_libs: [
         "liblog",
-        "libmediaextractor",
         "libmediandk",
     ],
 
diff --git a/media/extractors/midi/Android.bp b/media/extractors/midi/Android.bp
index 937e545..7d42e70 100644
--- a/media/extractors/midi/Android.bp
+++ b/media/extractors/midi/Android.bp
@@ -8,7 +8,6 @@
 
     shared_libs: [
         "liblog",
-        "libmediaextractor",
         "libmediandk",
     ],
 
diff --git a/media/extractors/midi/MidiExtractor.cpp b/media/extractors/midi/MidiExtractor.cpp
index cd39cec..43f394c 100644
--- a/media/extractors/midi/MidiExtractor.cpp
+++ b/media/extractors/midi/MidiExtractor.cpp
@@ -25,15 +25,14 @@
 #include <media/stagefright/MediaBufferGroup.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
-#include <media/stagefright/MetaData.h>
 #include <libsonivox/eas_reverb.h>
 
 namespace android {
 
-// how many Sonivox output buffers to aggregate into one MediaBufferBase
+// how many Sonivox output buffers to aggregate into one MediaBuffer
 static const int NUM_COMBINE_BUFFERS = 4;
 
-class MidiSource : public MediaTrackHelperV2 {
+class MidiSource : public MediaTrackHelperV3 {
 
 public:
     MidiSource(
@@ -45,7 +44,7 @@
     virtual media_status_t getFormat(AMediaFormat *);
 
     virtual media_status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
 protected:
     virtual ~MidiSource();
@@ -93,7 +92,7 @@
 
     CHECK(!mStarted);
     mStarted = true;
-    mEngine.allocateBuffers();
+    mEngine.allocateBuffers(mBufferGroup);
     return AMEDIA_OK;
 }
 
@@ -114,10 +113,10 @@
 }
 
 media_status_t MidiSource::read(
-        MediaBufferBase **outBuffer, const ReadOptions *options)
+        MediaBufferHelperV3 **outBuffer, const ReadOptions *options)
 {
     ALOGV("MidiSource::read");
-    MediaBufferBase *buffer;
+    MediaBufferHelperV3 *buffer;
     // process an optional seek request
     int64_t seekTimeUs;
     ReadOptions::SeekMode mode;
@@ -144,7 +143,6 @@
 MidiEngine::MidiEngine(CDataSource *dataSource,
         AMediaFormat *fileMetadata,
         AMediaFormat *trackMetadata) :
-            mGroup(NULL),
             mEasData(NULL),
             mEasHandle(NULL),
             mEasConfig(NULL),
@@ -194,7 +192,6 @@
     if (mEasData) {
         EAS_Shutdown(mEasData);
     }
-    delete mGroup;
     delete mIoWrapper;
 }
 
@@ -202,22 +199,20 @@
     return mIsInitialized ? OK : UNKNOWN_ERROR;
 }
 
-status_t MidiEngine::allocateBuffers() {
+status_t MidiEngine::allocateBuffers(MediaBufferGroupHelperV3 *group) {
     // select reverb preset and enable
     EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_PRESET, EAS_PARAM_REVERB_CHAMBER);
     EAS_SetParameter(mEasData, EAS_MODULE_REVERB, EAS_PARAM_REVERB_BYPASS, EAS_FALSE);
 
-    mGroup = new MediaBufferGroup;
     int bufsize = sizeof(EAS_PCM)
             * mEasConfig->mixBufferSize * mEasConfig->numChannels * NUM_COMBINE_BUFFERS;
     ALOGV("using %d byte buffer", bufsize);
-    mGroup->add_buffer(MediaBufferBase::Create(bufsize));
+    mGroup = group;
+    mGroup->add_buffer(bufsize);
     return OK;
 }
 
 status_t MidiEngine::releaseBuffers() {
-    delete mGroup;
-    mGroup = NULL;
     return OK;
 }
 
@@ -227,13 +222,13 @@
     return result == EAS_SUCCESS ? OK : UNKNOWN_ERROR;
 }
 
-MediaBufferBase* MidiEngine::readBuffer() {
+MediaBufferHelperV3* MidiEngine::readBuffer() {
     EAS_STATE state;
     EAS_State(mEasData, mEasHandle, &state);
     if ((state == EAS_STATE_STOPPED) || (state == EAS_STATE_ERROR)) {
         return NULL;
     }
-    MediaBufferBase *buffer;
+    MediaBufferHelperV3 *buffer;
     status_t err = mGroup->acquire_buffer(&buffer);
     if (err != OK) {
         ALOGE("readBuffer: no buffer");
@@ -242,7 +237,9 @@
     EAS_I32 timeMs;
     EAS_GetLocation(mEasData, mEasHandle, &timeMs);
     int64_t timeUs = 1000ll * timeMs;
-    buffer->meta_data().setInt64(kKeyTime, timeUs);
+    AMediaFormat *meta = buffer->meta_data();
+    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, timeUs);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
     EAS_PCM* p = (EAS_PCM*) buffer->data();
     int numBytesOutput = 0;
@@ -289,7 +286,7 @@
     return mInitCheck == OK ? 1 : 0;
 }
 
-MediaTrackHelperV2 *MidiExtractor::getTrack(size_t index)
+MediaTrackHelperV3 *MidiExtractor::getTrack(size_t index)
 {
     if (mInitCheck != OK || index > 0) {
         return NULL;
@@ -334,21 +331,21 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION_CURRENT,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("ef6cca0a-f8a2-43e6-ba5f-dfcd7c9a7ef2"),
         1,
         "MIDI Extractor",
         {
-            .v2 = [](
+            .v3 = [](
                 CDataSource *source,
                 float *confidence,
                 void **,
-                FreeMetaFunc *) -> CreatorFuncV2 {
+                FreeMetaFunc *) -> CreatorFuncV3 {
                 if (SniffMidi(source, confidence)) {
                     return [](
                             CDataSource *source,
-                            void *) -> CMediaExtractorV2* {
-                        return wrapV2(new MidiExtractor(source));};
+                            void *) -> CMediaExtractorV3* {
+                        return wrapV3(new MidiExtractor(source));};
                 }
                 return NULL;
             }
diff --git a/media/extractors/midi/MidiExtractor.h b/media/extractors/midi/MidiExtractor.h
index 412d6eb..ad345b8 100644
--- a/media/extractors/midi/MidiExtractor.h
+++ b/media/extractors/midi/MidiExtractor.h
@@ -38,26 +38,26 @@
 
     status_t initCheck();
 
-    status_t allocateBuffers();
+    status_t allocateBuffers(MediaBufferGroupHelperV3 *group);
     status_t releaseBuffers();
     status_t seekTo(int64_t positionUs);
-    MediaBufferBase* readBuffer();
+    MediaBufferHelperV3* readBuffer();
 private:
     MidiIoWrapper *mIoWrapper;
-    MediaBufferGroup *mGroup;
+    MediaBufferGroupHelperV3 *mGroup;
     EAS_DATA_HANDLE mEasData;
     EAS_HANDLE mEasHandle;
     const S_EAS_LIB_CONFIG* mEasConfig;
     bool mIsInitialized;
 };
 
-class MidiExtractor : public MediaExtractorPluginHelperV2 {
+class MidiExtractor : public MediaExtractorPluginHelperV3 {
 
 public:
     explicit MidiExtractor(CDataSource *source);
 
     virtual size_t countTracks();
-    virtual MediaTrackHelperV2 *getTrack(size_t index);
+    virtual MediaTrackHelperV3 *getTrack(size_t index);
     virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
     virtual media_status_t getMetaData(AMediaFormat *meta);
diff --git a/media/extractors/mp3/Android.bp b/media/extractors/mp3/Android.bp
index 97b687f..4e2f248 100644
--- a/media/extractors/mp3/Android.bp
+++ b/media/extractors/mp3/Android.bp
@@ -12,14 +12,13 @@
 
     shared_libs: [
         "liblog",
-        "libmediaextractor",
         "libmediandk",
-        "libstagefright_foundation",
     ],
 
     static_libs: [
         "libutils",
         "libstagefright_id3",
+        "libstagefright_foundation",
     ],
 
     name: "libmp3extractor",
diff --git a/media/extractors/mp3/MP3Extractor.cpp b/media/extractors/mp3/MP3Extractor.cpp
index 0e1ffb4..7abec54 100644
--- a/media/extractors/mp3/MP3Extractor.cpp
+++ b/media/extractors/mp3/MP3Extractor.cpp
@@ -207,7 +207,7 @@
     return valid;
 }
 
-class MP3Source : public MediaTrackHelperV2 {
+class MP3Source : public MediaTrackHelperV3 {
 public:
     MP3Source(
             AMediaFormat *meta, DataSourceHelper *source,
@@ -220,7 +220,7 @@
     virtual media_status_t getFormat(AMediaFormat *meta);
 
     virtual media_status_t read(
-            MediaBufferBase **buffer, const ReadOptions *options = NULL);
+            MediaBufferHelperV3 **buffer, const ReadOptions *options = NULL);
 
 protected:
     virtual ~MP3Source();
@@ -235,7 +235,6 @@
     int64_t mCurrentTimeUs;
     bool mStarted;
     MP3Seeker *mSeeker;
-    MediaBufferGroup *mGroup;
 
     int64_t mBasisTimeUs;
     int64_t mSamplesRead;
@@ -414,7 +413,7 @@
     return mInitCheck != OK ? 0 : 1;
 }
 
-MediaTrackHelperV2 *MP3Extractor::getTrack(size_t index) {
+MediaTrackHelperV3 *MP3Extractor::getTrack(size_t index) {
     if (mInitCheck != OK || index != 0) {
         return NULL;
     }
@@ -455,7 +454,6 @@
       mCurrentTimeUs(0),
       mStarted(false),
       mSeeker(seeker),
-      mGroup(NULL),
       mBasisTimeUs(0),
       mSamplesRead(0) {
 }
@@ -469,9 +467,7 @@
 media_status_t MP3Source::start() {
     CHECK(!mStarted);
 
-    mGroup = new MediaBufferGroup;
-
-    mGroup->add_buffer(MediaBufferBase::Create(kMaxFrameSize));
+    mBufferGroup->add_buffer(kMaxFrameSize);
 
     mCurrentPos = mFirstFramePos;
     mCurrentTimeUs = 0;
@@ -487,9 +483,6 @@
 media_status_t MP3Source::stop() {
     CHECK(mStarted);
 
-    delete mGroup;
-    mGroup = NULL;
-
     mStarted = false;
 
     return AMEDIA_OK;
@@ -500,7 +493,7 @@
 }
 
 media_status_t MP3Source::read(
-        MediaBufferBase **out, const ReadOptions *options) {
+        MediaBufferHelperV3 **out, const ReadOptions *options) {
     *out = NULL;
 
     int64_t seekTimeUs;
@@ -530,8 +523,8 @@
         mSamplesRead = 0;
     }
 
-    MediaBufferBase *buffer;
-    status_t err = mGroup->acquire_buffer(&buffer);
+    MediaBufferHelperV3 *buffer;
+    status_t err = mBufferGroup->acquire_buffer(&buffer);
     if (err != OK) {
         return AMEDIA_ERROR_UNKNOWN;
     }
@@ -597,8 +590,9 @@
 
     buffer->set_range(0, frame_size);
 
-    buffer->meta_data().setInt64(kKeyTime, mCurrentTimeUs);
-    buffer->meta_data().setInt32(kKeyIsSyncFrame, 1);
+    AMediaFormat *meta = buffer->meta_data();
+    AMediaFormat_setInt64(meta, AMEDIAFORMAT_KEY_TIME_US, mCurrentTimeUs);
+    AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_IS_SYNC_FRAME, 1);
 
     mCurrentPos += frame_size;
 
@@ -674,14 +668,14 @@
     return AMEDIA_OK;
 }
 
-static CMediaExtractorV2* CreateExtractor(
+static CMediaExtractorV3* CreateExtractor(
         CDataSource *source,
         void *meta) {
     Mp3Meta *metaData = static_cast<Mp3Meta *>(meta);
-    return wrapV2(new MP3Extractor(new DataSourceHelper(source), metaData));
+    return wrapV3(new MP3Extractor(new DataSourceHelper(source), metaData));
 }
 
-static CreatorFuncV2 Sniff(
+static CreatorFuncV3 Sniff(
         CDataSource *source, float *confidence, void **meta,
         FreeMetaFunc *freeMeta) {
     off64_t pos = 0;
@@ -718,11 +712,11 @@
 __attribute__ ((visibility ("default")))
 ExtractorDef GETEXTRACTORDEF() {
     return {
-        EXTRACTORDEF_VERSION_CURRENT,
+        EXTRACTORDEF_VERSION_CURRENT + 1,
         UUID("812a3f6c-c8cf-46de-b529-3774b14103d4"),
         1, // version
         "MP3 Extractor",
-        { .v2 = Sniff }
+        { .v3 = Sniff }
     };
 }
 
diff --git a/media/extractors/mp3/MP3Extractor.h b/media/extractors/mp3/MP3Extractor.h
index 22547e2..fe72cff 100644
--- a/media/extractors/mp3/MP3Extractor.h
+++ b/media/extractors/mp3/MP3Extractor.h
@@ -32,13 +32,13 @@
 class String8;
 struct Mp3Meta;
 
-class MP3Extractor : public MediaExtractorPluginHelperV2 {
+class MP3Extractor : public MediaExtractorPluginHelperV3 {
 public:
     MP3Extractor(DataSourceHelper *source, Mp3Meta *meta);
     ~MP3Extractor();
 
     virtual size_t countTracks();
-    virtual MediaTrackHelperV2 *getTrack(size_t index);
+    virtual MediaTrackHelperV3 *getTrack(size_t index);
     virtual media_status_t getTrackMetaData(AMediaFormat *meta, size_t index, uint32_t flags);
 
     virtual media_status_t getMetaData(AMediaFormat *meta);
diff --git a/media/extractors/wav/WAVExtractor.cpp b/media/extractors/wav/WAVExtractor.cpp
index 17b5f81..1f0aae5 100644
--- a/media/extractors/wav/WAVExtractor.cpp
+++ b/media/extractors/wav/WAVExtractor.cpp
@@ -383,7 +383,6 @@
 }
 
 WAVSource::~WAVSource() {
-    ALOGI("~WAVSource");
     if (mStarted) {
         stop();
     }
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 163cd99..02bb4e0 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -137,6 +137,7 @@
 
     shared_libs: [
         "libaudioutils",
+        "libbase",
         "libbinder",
         "libcamera_client",
         "libcutils",
@@ -197,12 +198,6 @@
         "include",
     ],
 
-    // This is needed to make sure libcodec2 exists in all devices.
-    // TODO: Remove this once the public CCodec is enabled.
-    required: [
-        "libcodec2",
-    ],
-
     cflags: [
         "-Wno-multichar",
         "-Werror",
diff --git a/media/libstagefright/MediaTrack.cpp b/media/libstagefright/MediaTrack.cpp
index daed5a0..6c0f989 100644
--- a/media/libstagefright/MediaTrack.cpp
+++ b/media/libstagefright/MediaTrack.cpp
@@ -212,9 +212,13 @@
         // only convert the keys we're actually expecting, as doing
         // the full convertMessageToMetadata() for every buffer is
         // too expensive
-        int64_t val;
-        if (format->mFormat->findInt64("timeUs", &val)) {
-            meta.setInt64(kKeyTime, val);
+        int64_t val64;
+        if (format->mFormat->findInt64("timeUs", &val64)) {
+            meta.setInt64(kKeyTime, val64);
+        }
+        int32_t val32;
+        if (format->mFormat->findInt32("is-sync-frame", &val32)) {
+            meta.setInt32(kKeyIsSyncFrame, val32);
         }
     } else {
         *buffer = nullptr;
diff --git a/media/libstagefright/StagefrightPluginLoader.cpp b/media/libstagefright/StagefrightPluginLoader.cpp
index dd5903a..26d7dff 100644
--- a/media/libstagefright/StagefrightPluginLoader.cpp
+++ b/media/libstagefright/StagefrightPluginLoader.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "StagefrightPluginLoader"
 #include <utils/Log.h>
 
+#include <android-base/properties.h>
 #include <dlfcn.h>
 
 #include "StagefrightPluginLoader.h"
@@ -27,9 +28,19 @@
 /* static */ Mutex StagefrightPluginLoader::sMutex;
 /* static */ std::unique_ptr<StagefrightPluginLoader> StagefrightPluginLoader::sInstance;
 
+namespace /* unnamed */ {
+
+constexpr const char kCCodecPluginPath[] = "libsfplugin_ccodec.so";
+
+}  // unnamed namespace
+
 StagefrightPluginLoader::StagefrightPluginLoader(const char *libPath)
     : mCreateCodec(nullptr),
       mCreateBuilder(nullptr) {
+    if (android::base::GetIntProperty("debug.media.codec2", 0) == 0) {
+        ALOGD("CCodec is disabled.");
+        return;
+    }
     mLibHandle = dlopen(libPath, RTLD_NOW | RTLD_NODELETE);
     if (mLibHandle == nullptr) {
         ALOGD("Failed to load library: %s (%s)", libPath, dlerror());
@@ -87,7 +98,7 @@
     Mutex::Autolock _l(sMutex);
     if (!sInstance) {
         ALOGV("Loading library");
-        sInstance.reset(new StagefrightPluginLoader("libstagefright_ccodec.so"));
+        sInstance.reset(new StagefrightPluginLoader(kCCodecPluginPath));
     }
     return sInstance;
 }
diff --git a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
index e55c2e7..d644207 100644
--- a/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
+++ b/media/libstagefright/codecs/mp3dec/src/pvmp3_get_side_info.cpp
@@ -127,13 +127,13 @@
         {
             tmp = getbits_crc(inputStream, 14, crc, info->error_protection);
             si->main_data_begin = (tmp << 18) >> 23;    /* 9 */
-            si->private_bits    = (tmp << 23) >> 27;    /* 5 */
+            si->private_bits    = (tmp << 27) >> 27;    /* 5 */
         }
         else
         {
             tmp = getbits_crc(inputStream, 12, crc, info->error_protection);
             si->main_data_begin = (tmp << 20) >> 23;    /* 9 */
-            si->private_bits    = (tmp << 23) >> 29;    /* 3 */
+            si->private_bits    = (tmp << 29) >> 29;    /* 3 */
 
         }
 
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 8267ba5..e355183 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -104,6 +104,7 @@
             enabled: false,
         },
     },
+    version_script: "libmediandk.map.txt",
 }
 
 llndk_library {
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 4be1928..13d9135 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -184,9 +184,6 @@
 extern const char* AMEDIAFORMAT_KEY_AUTHOR __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_BITS_PER_SAMPLE __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CDTRACKNUMBER __INTRODUCED_IN(29);
-extern const char* AMEDIAFORMAT_KEY_COLOR_RANGE __INTRODUCED_IN(29);
-extern const char* AMEDIAFORMAT_KEY_COLOR_STANDARD __INTRODUCED_IN(29);
-extern const char* AMEDIAFORMAT_KEY_COLOR_TRANSFER __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_COMPILATION __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_COMPOSER __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE __INTRODUCED_IN(29);
@@ -207,7 +204,6 @@
 extern const char* AMEDIAFORMAT_KEY_EXIF_SIZE __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_FRAME_COUNT __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_GENRE __INTRODUCED_IN(29);
-extern const char* AMEDIAFORMAT_KEY_HDR_STATIC_INFO __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_ICC_PROFILE __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_IS_SYNC_FRAME __INTRODUCED_IN(29);
 extern const char* AMEDIAFORMAT_KEY_LOCATION __INTRODUCED_IN(29);
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index d3bdbae..88736ab 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -35,64 +35,110 @@
     AMEDIAFORMAT_KEY_AAC_MAX_OUTPUT_CHANNEL_COUNT; # var introduced=28
     AMEDIAFORMAT_KEY_AAC_PROFILE; # var introduced=21
     AMEDIAFORMAT_KEY_AAC_SBR_MODE; # var introduced=28
+    AMEDIAFORMAT_KEY_ALBUM; # var introduced=29
+    AMEDIAFORMAT_KEY_ALBUMART; # var introduced=29
+    AMEDIAFORMAT_KEY_ALBUMARTIST; # var introduced=29
+    AMEDIAFORMAT_KEY_ARTIST; # var introduced=29
+    AMEDIAFORMAT_KEY_AUDIO_PRESENTATION_INFO; # var introduced=29
     AMEDIAFORMAT_KEY_AUDIO_SESSION_ID; # var introduced=28
+    AMEDIAFORMAT_KEY_AUTHOR; # var introduced=29
     AMEDIAFORMAT_KEY_BITRATE_MODE; # var introduced=28
     AMEDIAFORMAT_KEY_BIT_RATE; # var introduced=21
+    AMEDIAFORMAT_KEY_BITS_PER_SAMPLE; # var introduced=29
     AMEDIAFORMAT_KEY_CAPTURE_RATE; # var introduced=28
+    AMEDIAFORMAT_KEY_CDTRACKNUMBER; # var introduced=29
     AMEDIAFORMAT_KEY_CHANNEL_COUNT; # var introduced=21
     AMEDIAFORMAT_KEY_CHANNEL_MASK; # var introduced=21
     AMEDIAFORMAT_KEY_COLOR_FORMAT; # var introduced=21
     AMEDIAFORMAT_KEY_COLOR_RANGE; # var introduced=28
     AMEDIAFORMAT_KEY_COLOR_STANDARD; # var introduced=28
     AMEDIAFORMAT_KEY_COLOR_TRANSFER; # var introduced=28
+    AMEDIAFORMAT_KEY_COMPILATION; # var introduced=29
     AMEDIAFORMAT_KEY_COMPLEXITY; # var introduced=28
+    AMEDIAFORMAT_KEY_COMPOSER; # var introduced=29
+    AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE; # var introduced=29
+    AMEDIAFORMAT_KEY_CRYPTO_ENCRYPTED_BYTE_BLOCK; # var introduced=29
+    AMEDIAFORMAT_KEY_CRYPTO_IV; # var introduced=29
+    AMEDIAFORMAT_KEY_CRYPTO_KEY; # var introduced=29
+    AMEDIAFORMAT_KEY_CRYPTO_MODE; # var introduced=29
+    AMEDIAFORMAT_KEY_CRYPTO_SKIP_BYTE_BLOCK; # var introduced=29
     AMEDIAFORMAT_KEY_CSD; # var introduced=28
     AMEDIAFORMAT_KEY_CSD_0; # var introduced=28
     AMEDIAFORMAT_KEY_CSD_1; # var introduced=28
     AMEDIAFORMAT_KEY_CSD_2; # var introduced=28
+    AMEDIAFORMAT_KEY_CSD_AVC; # var introduced=29
+    AMEDIAFORMAT_KEY_CSD_HEVC; # var introduced=29
+    AMEDIAFORMAT_KEY_D263; # var introduced=29
+    AMEDIAFORMAT_KEY_DATE; # var introduced=29
+    AMEDIAFORMAT_KEY_DISCNUMBER; # var introduced=29
     AMEDIAFORMAT_KEY_DISPLAY_CROP; # var introduced=28
     AMEDIAFORMAT_KEY_DISPLAY_HEIGHT; # var introduced=28
     AMEDIAFORMAT_KEY_DISPLAY_WIDTH; # var introduced=28
     AMEDIAFORMAT_KEY_DURATION; # var introduced=21
+    AMEDIAFORMAT_KEY_ENCODER_DELAY; # var introduced=29
+    AMEDIAFORMAT_KEY_ENCODER_PADDING; # var introduced=29
+    AMEDIAFORMAT_KEY_ESDS; # var introduced=29
+    AMEDIAFORMAT_KEY_EXIF_OFFSET; # var introduced=29
+    AMEDIAFORMAT_KEY_EXIF_SIZE; # var introduced=29
+    AMEDIAFORMAT_KEY_FRAME_COUNT; # var introduced=29
     AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL; # var introduced=21
     AMEDIAFORMAT_KEY_FRAME_RATE; # var introduced=21
+    AMEDIAFORMAT_KEY_GENRE; # var introduced=29
     AMEDIAFORMAT_KEY_GRID_COLUMNS; # var introduced=28
     AMEDIAFORMAT_KEY_GRID_ROWS; # var introduced=28
     AMEDIAFORMAT_KEY_HDR_STATIC_INFO; # var introduced=28
     AMEDIAFORMAT_KEY_HEIGHT; # var introduced=21
+    AMEDIAFORMAT_KEY_ICC_PROFILE; # var introduced=29
     AMEDIAFORMAT_KEY_INTRA_REFRESH_PERIOD; # var introduced=28
     AMEDIAFORMAT_KEY_IS_ADTS; # var introduced=21
     AMEDIAFORMAT_KEY_IS_AUTOSELECT; # var introduced=21
     AMEDIAFORMAT_KEY_IS_DEFAULT; # var introduced=21
     AMEDIAFORMAT_KEY_IS_FORCED_SUBTITLE; # var introduced=21
+    AMEDIAFORMAT_KEY_IS_SYNC_FRAME; # var introduced=29
     AMEDIAFORMAT_KEY_I_FRAME_INTERVAL; # var introduced=21
     AMEDIAFORMAT_KEY_LANGUAGE; # var introduced=21
     AMEDIAFORMAT_KEY_LATENCY; # var introduced=28
     AMEDIAFORMAT_KEY_LEVEL; # var introduced=28
+    AMEDIAFORMAT_KEY_LOCATION; # var introduced=29
+    AMEDIAFORMAT_KEY_LOOP; # var introduced=29
+    AMEDIAFORMAT_KEY_LYRICIST; # var introduced=29
+    AMEDIAFORMAT_KEY_MAX_BIT_RATE; # var introduced=29
     AMEDIAFORMAT_KEY_MAX_HEIGHT; # var introduced=21
     AMEDIAFORMAT_KEY_MAX_INPUT_SIZE; # var introduced=21
     AMEDIAFORMAT_KEY_MAX_WIDTH; # var introduced=21
     AMEDIAFORMAT_KEY_MIME; # var introduced=21
     AMEDIAFORMAT_KEY_MPEG_USER_DATA; # var introduced=28
+    AMEDIAFORMAT_KEY_MPEG2_STREAM_HEADER; # var introduced=29
     AMEDIAFORMAT_KEY_OPERATING_RATE; # var introduced=28
+    AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN; # var introduced=29
     AMEDIAFORMAT_KEY_PCM_ENCODING; # var introduced=28
     AMEDIAFORMAT_KEY_PRIORITY; # var introduced=28
     AMEDIAFORMAT_KEY_PROFILE; # var introduced=28
+    AMEDIAFORMAT_KEY_PSSH; # var introduced=29
     AMEDIAFORMAT_KEY_PUSH_BLANK_BUFFERS_ON_STOP; # var introduced=21
     AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER; # var introduced=21
     AMEDIAFORMAT_KEY_ROTATION; # var introduced=28
     AMEDIAFORMAT_KEY_SAMPLE_RATE; # var introduced=21
+    AMEDIAFORMAT_KEY_SAR_HEIGHT; # var introduced=29
+    AMEDIAFORMAT_KEY_SAR_WIDTH; # var introduced=29
     AMEDIAFORMAT_KEY_SEI; # var introduced=28
     AMEDIAFORMAT_KEY_SLICE_HEIGHT; # var introduced=28
     AMEDIAFORMAT_KEY_STRIDE; # var introduced=21
+    AMEDIAFORMAT_KEY_TEMPORAL_LAYER_COUNT; # var introduced=29
     AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID; # var introduced=28
     AMEDIAFORMAT_KEY_TEMPORAL_LAYERING; # var introduced=28
+    AMEDIAFORMAT_KEY_TEXT_FORMAT_DATA; # var introduced=29
+    AMEDIAFORMAT_KEY_THUMBNAIL_HEIGHT; # var introduced=29
+    AMEDIAFORMAT_KEY_THUMBNAIL_TIME; # var introduced=29
+    AMEDIAFORMAT_KEY_THUMBNAIL_WIDTH; # var introduced=29
+    AMEDIAFORMAT_KEY_TITLE; # var introduced=28
     AMEDIAFORMAT_KEY_TILE_HEIGHT; # var introduced=28
     AMEDIAFORMAT_KEY_TILE_WIDTH; # var introduced=28
     AMEDIAFORMAT_KEY_TIME_US; # var introduced=28
     AMEDIAFORMAT_KEY_TRACK_INDEX; # var introduced=28
     AMEDIAFORMAT_KEY_TRACK_ID; # var introduced=28
     AMEDIAFORMAT_KEY_WIDTH; # var introduced=21
+    AMEDIAFORMAT_KEY_YEAR; # var introduced=29
     AMediaCodecActionCode_isRecoverable; # introduced=28
     AMediaCodecActionCode_isTransient; # introduced=28
     AMediaCodecCryptoInfo_delete;
@@ -112,6 +158,7 @@
     AMediaCodec_dequeueInputBuffer;
     AMediaCodec_dequeueOutputBuffer;
     AMediaCodec_flush;
+    AMediaCodec_getBufferFormat; # introduced=21
     AMediaCodec_getInputBuffer;
     AMediaCodec_getInputFormat; # introduced=28
     AMediaCodec_getName; # introduced=28
diff --git a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
index e3cc1ba..04dc0b8 100644
--- a/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
+++ b/packages/MediaComponents/apex/java/android/media/session/MediaSession.java
@@ -179,7 +179,9 @@
         MediaSessionManager manager = (MediaSessionManager) context
                 .getSystemService(Context.MEDIA_SESSION_SERVICE);
         try {
-            mBinder = manager.createSession(mCbStub, tag, userId);
+            //TODO(b/119749862): Resolve hidden API usage. MediaSessioManager#createSession
+            //mBinder = manager.createSession(mCbStub, tag, userId);
+            mBinder = null;  //TODO: remove this.
             mSessionToken = new Token(mBinder.getController());
             mController = new MediaController(context, mSessionToken);
         } catch (RemoteException e) {
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 32b07fa..6003607 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -2215,6 +2215,8 @@
     sCameraService->removeByClient(this);
     sCameraService->logDisconnected(mCameraIdStr, mClientPid,
             String8(mClientPackageName));
+    sCameraService->mCameraProviderManager->removeRef(CameraProviderManager::DeviceMode::CAMERA,
+            mCameraIdStr.c_str());
 
     sp<IBinder> remote = getRemote();
     if (remote != nullptr) {
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index a82f0f7..a9cbe72 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -24,23 +24,37 @@
 
 #include <algorithm>
 #include <chrono>
+#include <future>
 #include <inttypes.h>
 #include <hardware/camera_common.h>
 #include <hidl/ServiceManagement.h>
 #include <functional>
 #include <camera_metadata_hidden.h>
 #include <android-base/parseint.h>
+#include <android-base/logging.h>
+#include <cutils/properties.h>
+#include <hwbinder/IPCThreadState.h>
+#include <utils/Trace.h>
 
 namespace android {
 
 using namespace ::android::hardware::camera;
 using namespace ::android::hardware::camera::common::V1_0;
+using std::literals::chrono_literals::operator""s;
 
 namespace {
 // Hardcoded name for the passthrough HAL implementation, since it can't be discovered via the
 // service manager
 const std::string kLegacyProviderName("legacy/0");
 const std::string kExternalProviderName("external/0");
+const bool kEnableLazyHal(property_get_bool("ro.camera.enableLazyHal", false));
+
+// The extra amount of time to hold a reference to an ICameraProvider after it is no longer needed.
+// Hold the reference for this extra time so that if the camera is unreferenced and then referenced
+// again quickly, we do not let the HAL exit and then need to immediately restart it. An example
+// when this could happen is switching from a front-facing to a rear-facing camera. If the HAL were
+// to exit during the camera switch, the camera could appear janky to the user.
+const std::chrono::system_clock::duration kCameraKeepAliveDelay = 3s;
 
 } // anonymous namespace
 
@@ -74,6 +88,8 @@
     addProviderLocked(kLegacyProviderName, /*expected*/ false);
     addProviderLocked(kExternalProviderName, /*expected*/ false);
 
+    IPCThreadState::self()->flushCommands();
+
     return OK;
 }
 
@@ -219,26 +235,15 @@
     return OK;
 }
 
-bool CameraProviderManager::supportSetTorchMode(const std::string &id) {
+bool CameraProviderManager::supportSetTorchMode(const std::string &id) const {
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
-    bool support = false;
     for (auto& provider : mProviders) {
         auto deviceInfo = findDeviceInfoLocked(id);
         if (deviceInfo != nullptr) {
-            auto ret = provider->mInterface->isSetTorchModeSupported(
-                [&support](auto status, bool supported) {
-                    if (status == Status::OK) {
-                        support = supported;
-                    }
-                });
-            if (!ret.isOk()) {
-                ALOGE("%s: Transaction error checking torch mode support '%s': %s",
-                        __FUNCTION__, provider->mProviderName.c_str(), ret.description().c_str());
-            }
-            break;
+            return provider->mSetTorchModeSupported;
         }
     }
-    return support;
+    return false;
 }
 
 status_t CameraProviderManager::setTorchMode(const std::string &id, bool enabled) {
@@ -247,6 +252,15 @@
     auto deviceInfo = findDeviceInfoLocked(id);
     if (deviceInfo == nullptr) return NAME_NOT_FOUND;
 
+    // Pass the camera ID to start interface so that it will save it to the map of ICameraProviders
+    // that are currently in use.
+    const sp<provider::V2_4::ICameraProvider> interface =
+            deviceInfo->mParentProvider->startProviderInterface();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    saveRef(DeviceMode::TORCH, deviceInfo->mId, interface);
+
     return deviceInfo->setTorchMode(enabled);
 }
 
@@ -254,37 +268,7 @@
     sp<VendorTagDescriptorCache> tagCache = new VendorTagDescriptorCache();
 
     for (auto& provider : mProviders) {
-        hardware::hidl_vec<VendorTagSection> vts;
-        Status status;
-        hardware::Return<void> ret;
-        ret = provider->mInterface->getVendorTags(
-            [&](auto s, const auto& vendorTagSecs) {
-                status = s;
-                if (s == Status::OK) {
-                    vts = vendorTagSecs;
-                }
-        });
-        if (!ret.isOk()) {
-            ALOGE("%s: Transaction error getting vendor tags from provider '%s': %s",
-                    __FUNCTION__, provider->mProviderName.c_str(), ret.description().c_str());
-            return DEAD_OBJECT;
-        }
-        if (status != Status::OK) {
-            return mapToStatusT(status);
-        }
-
-        // Read all vendor tag definitions into a descriptor
-        sp<VendorTagDescriptor> desc;
-        status_t res;
-        if ((res = HidlVendorTagDescriptor::createDescriptorFromHidl(vts, /*out*/desc))
-                != OK) {
-            ALOGE("%s: Could not generate descriptor from vendor tag operations,"
-                  "received error %s (%d). Camera clients will not be able to use"
-                  "vendor tags", __FUNCTION__, strerror(res), res);
-            return res;
-        }
-
-        tagCache->addVendorDescriptor(provider->mProviderTagid, desc);
+        tagCache->addVendorDescriptor(provider->mProviderTagid, provider->mVendorTagDescriptor);
     }
 
     VendorTagDescriptorCache::setAsGlobalVendorTagCache(tagCache);
@@ -293,9 +277,9 @@
 }
 
 status_t CameraProviderManager::openSession(const std::string &id,
-        const sp<hardware::camera::device::V3_2::ICameraDeviceCallback>& callback,
+        const sp<device::V3_2::ICameraDeviceCallback>& callback,
         /*out*/
-        sp<hardware::camera::device::V3_2::ICameraDeviceSession> *session) {
+        sp<device::V3_2::ICameraDeviceSession> *session) {
 
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
 
@@ -304,10 +288,22 @@
     if (deviceInfo == nullptr) return NAME_NOT_FOUND;
 
     auto *deviceInfo3 = static_cast<ProviderInfo::DeviceInfo3*>(deviceInfo);
+    const sp<provider::V2_4::ICameraProvider> provider =
+            deviceInfo->mParentProvider->startProviderInterface();
+    if (provider == nullptr) {
+        return DEAD_OBJECT;
+    }
+    saveRef(DeviceMode::CAMERA, id, provider);
 
     Status status;
     hardware::Return<void> ret;
-    ret = deviceInfo3->mInterface->open(callback, [&status, &session]
+    auto interface = deviceInfo3->startDeviceInterface<
+            CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+
+    ret = interface->open(callback, [&status, &session]
             (Status s, const sp<device::V3_2::ICameraDeviceSession>& cameraSession) {
                 status = s;
                 if (status == Status::OK) {
@@ -315,6 +311,7 @@
                 }
             });
     if (!ret.isOk()) {
+        removeRef(DeviceMode::CAMERA, id);
         ALOGE("%s: Transaction error opening a session for camera device %s: %s",
                 __FUNCTION__, id.c_str(), ret.description().c_str());
         return DEAD_OBJECT;
@@ -323,9 +320,9 @@
 }
 
 status_t CameraProviderManager::openSession(const std::string &id,
-        const sp<hardware::camera::device::V1_0::ICameraDeviceCallback>& callback,
+        const sp<device::V1_0::ICameraDeviceCallback>& callback,
         /*out*/
-        sp<hardware::camera::device::V1_0::ICameraDevice> *session) {
+        sp<device::V1_0::ICameraDevice> *session) {
 
     std::lock_guard<std::mutex> lock(mInterfaceMutex);
 
@@ -334,19 +331,82 @@
     if (deviceInfo == nullptr) return NAME_NOT_FOUND;
 
     auto *deviceInfo1 = static_cast<ProviderInfo::DeviceInfo1*>(deviceInfo);
+    const sp<provider::V2_4::ICameraProvider> provider =
+            deviceInfo->mParentProvider->startProviderInterface();
+    if (provider == nullptr) {
+        return DEAD_OBJECT;
+    }
+    saveRef(DeviceMode::CAMERA, id, provider);
 
-    hardware::Return<Status> status = deviceInfo1->mInterface->open(callback);
+    auto interface = deviceInfo1->startDeviceInterface<
+            CameraProviderManager::ProviderInfo::DeviceInfo1::InterfaceT>();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    hardware::Return<Status> status = interface->open(callback);
     if (!status.isOk()) {
+        removeRef(DeviceMode::CAMERA, id);
         ALOGE("%s: Transaction error opening a session for camera device %s: %s",
                 __FUNCTION__, id.c_str(), status.description().c_str());
         return DEAD_OBJECT;
     }
     if (status == Status::OK) {
-        *session = deviceInfo1->mInterface;
+        *session = interface;
     }
     return mapToStatusT(status);
 }
 
+void CameraProviderManager::saveRef(DeviceMode usageType, const std::string &cameraId,
+        sp<provider::V2_4::ICameraProvider> provider) {
+    if (!kEnableLazyHal) {
+        return;
+    }
+    ALOGI("Saving camera provider %s for camera device %s", provider->descriptor, cameraId.c_str());
+    std::lock_guard<std::mutex> lock(mProviderInterfaceMapLock);
+    std::unordered_map<std::string, sp<provider::V2_4::ICameraProvider>> *primaryMap, *alternateMap;
+    if (usageType == DeviceMode::TORCH) {
+        primaryMap = &mTorchProviderByCameraId;
+        alternateMap = &mCameraProviderByCameraId;
+    } else {
+        primaryMap = &mCameraProviderByCameraId;
+        alternateMap = &mTorchProviderByCameraId;
+    }
+    auto id = cameraId.c_str();
+    (*primaryMap)[id] = provider;
+    auto search = alternateMap->find(id);
+    if (search != alternateMap->end()) {
+        ALOGW("%s: Camera device %s is using both torch mode and camera mode simultaneously. "
+                "That should not be possible", __FUNCTION__, id);
+    }
+    ALOGV("%s: Camera device %s connected", __FUNCTION__, id);
+}
+
+void CameraProviderManager::removeRef(DeviceMode usageType, const std::string &cameraId) {
+    if (!kEnableLazyHal) {
+        return;
+    }
+    ALOGI("Removing camera device %s", cameraId.c_str());
+    std::unordered_map<std::string, sp<provider::V2_4::ICameraProvider>> *providerMap;
+    if (usageType == DeviceMode::TORCH) {
+        providerMap = &mTorchProviderByCameraId;
+    } else {
+        providerMap = &mCameraProviderByCameraId;
+    }
+    std::lock_guard<std::mutex> lock(mProviderInterfaceMapLock);
+    auto search = providerMap->find(cameraId.c_str());
+    if (search != providerMap->end()) {
+        auto ptr = search->second;
+        auto future = std::async(std::launch::async, [ptr] {
+            std::this_thread::sleep_for(kCameraKeepAliveDelay);
+            IPCThreadState::self()->flushCommands();
+        });
+        providerMap->erase(cameraId.c_str());
+    } else {
+        ALOGE("%s: Asked to remove reference for camera %s, but no reference to it was found. This "
+                "could mean removeRef was called twice for the same camera ID.", __FUNCTION__,
+                cameraId.c_str());
+    }
+}
 
 hardware::Return<void> CameraProviderManager::onRegistration(
         const hardware::hidl_string& /*fqName*/,
@@ -364,6 +424,8 @@
         listener->onNewProviderRegistered();
     }
 
+    IPCThreadState::self()->flushCommands();
+
     return hardware::Return<void>();
 }
 
@@ -611,9 +673,8 @@
         }
     }
 
-    sp<ProviderInfo> providerInfo =
-            new ProviderInfo(newProvider, interface, this);
-    status_t res = providerInfo->initialize();
+    sp<ProviderInfo> providerInfo = new ProviderInfo(newProvider, this);
+    status_t res = providerInfo->initialize(interface);
     if (res != OK) {
         return res;
     }
@@ -665,27 +726,26 @@
 
 CameraProviderManager::ProviderInfo::ProviderInfo(
         const std::string &providerName,
-        sp<provider::V2_4::ICameraProvider>& interface,
         CameraProviderManager *manager) :
         mProviderName(providerName),
-        mInterface(interface),
         mProviderTagid(generateVendorTagId(providerName)),
         mUniqueDeviceCount(0),
         mManager(manager) {
     (void) mManager;
 }
 
-status_t CameraProviderManager::ProviderInfo::initialize() {
+status_t CameraProviderManager::ProviderInfo::initialize(
+        sp<provider::V2_4::ICameraProvider>& interface) {
     status_t res = parseProviderName(mProviderName, &mType, &mId);
     if (res != OK) {
         ALOGE("%s: Invalid provider name, ignoring", __FUNCTION__);
         return BAD_VALUE;
     }
     ALOGI("Connecting to new camera provider: %s, isRemote? %d",
-            mProviderName.c_str(), mInterface->isRemote());
+            mProviderName.c_str(), interface->isRemote());
     // cameraDeviceStatusChange callbacks may be called (and causing new devices added)
     // before setCallback returns
-    hardware::Return<Status> status = mInterface->setCallback(this);
+    hardware::Return<Status> status = interface->setCallback(this);
     if (!status.isOk()) {
         ALOGE("%s: Transaction error setting up callbacks with camera provider '%s': %s",
                 __FUNCTION__, mProviderName.c_str(), status.description().c_str());
@@ -697,7 +757,7 @@
         return mapToStatusT(status);
     }
 
-    hardware::Return<bool> linked = mInterface->linkToDeath(this, /*cookie*/ mId);
+    hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
     if (!linked.isOk()) {
         ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
                 __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
@@ -709,7 +769,7 @@
 
     // Get initial list of camera devices, if any
     std::vector<std::string> devices;
-    hardware::Return<void> ret = mInterface->getCameraIdList([&status, this, &devices](
+    hardware::Return<void> ret = interface->getCameraIdList([&status, this, &devices](
             Status idStatus,
             const hardware::hidl_vec<hardware::hidl_string>& cameraDeviceNames) {
         status = idStatus;
@@ -738,11 +798,24 @@
         return mapToStatusT(status);
     }
 
+    ret = interface->isSetTorchModeSupported(
+        [this](auto status, bool supported) {
+            if (status == Status::OK) {
+                mSetTorchModeSupported = supported;
+            }
+        });
+    if (!ret.isOk()) {
+        ALOGE("%s: Transaction error checking torch mode support '%s': %s",
+                __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
+        return DEAD_OBJECT;
+    }
+
+    mIsRemote = interface->isRemote();
+
     sp<StatusListener> listener = mManager->getStatusListener();
     for (auto& device : devices) {
         std::string id;
-        status_t res = addDevice(device,
-                hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT, &id);
+        status_t res = addDevice(device, common::V1_0::CameraDeviceStatus::PRESENT, &id);
         if (res != OK) {
             ALOGE("%s: Unable to enumerate camera device '%s': %s (%d)",
                     __FUNCTION__, device.c_str(), strerror(-res), res);
@@ -750,13 +823,53 @@
         }
     }
 
+    res = setUpVendorTags();
+    if (res != OK) {
+        ALOGE("%s: Unable to set up vendor tags from provider '%s'",
+                __FUNCTION__, mProviderName.c_str());
+        return res;
+    }
+
     ALOGI("Camera provider %s ready with %zu camera devices",
             mProviderName.c_str(), mDevices.size());
 
     mInitialized = true;
+    if (!kEnableLazyHal) {
+        // Save HAL reference indefinitely
+        mSavedInterface = interface;
+    }
     return OK;
 }
 
+const sp<provider::V2_4::ICameraProvider>
+CameraProviderManager::ProviderInfo::startProviderInterface() {
+    ATRACE_CALL();
+    ALOGI("Request to start camera provider: %s", mProviderName.c_str());
+    if (mSavedInterface != nullptr) {
+        return mSavedInterface;
+    }
+    auto interface = mActiveInterface.promote();
+    if (interface == nullptr) {
+        ALOGI("Could not promote, calling getService(%s)", mProviderName.c_str());
+        interface = mManager->mServiceProxy->getService(mProviderName);
+        interface->setCallback(this);
+        hardware::Return<bool> linked = interface->linkToDeath(this, /*cookie*/ mId);
+        if (!linked.isOk()) {
+            ALOGE("%s: Transaction error in linking to camera provider '%s' death: %s",
+                    __FUNCTION__, mProviderName.c_str(), linked.description().c_str());
+            mManager->removeProvider(mProviderName);
+            return nullptr;
+        } else if (!linked) {
+            ALOGW("%s: Unable to link to provider '%s' death notifications",
+                    __FUNCTION__, mProviderName.c_str());
+        }
+        mActiveInterface = interface;
+    } else {
+        ALOGI("Camera provider (%s) already in use. Re-using instance.", mProviderName.c_str());
+    }
+    return interface;
+}
+
 const std::string& CameraProviderManager::ProviderInfo::getType() const {
     return mType;
 }
@@ -838,7 +951,7 @@
 
 status_t CameraProviderManager::ProviderInfo::dump(int fd, const Vector<String16>&) const {
     dprintf(fd, "== Camera Provider HAL %s (v2.4, %s) static info: %zu devices: ==\n",
-            mProviderName.c_str(), mInterface->isRemote() ? "remote" : "passthrough",
+            mProviderName.c_str(), mIsRemote ? "remote" : "passthrough",
             mDevices.size());
 
     for (auto& device : mDevices) {
@@ -966,6 +1079,9 @@
                         torchStatusToString(newStatus));
                 id = deviceInfo->mId;
                 known = true;
+                if (TorchModeStatus::AVAILABLE_ON != newStatus) {
+                    mManager->removeRef(DeviceMode::TORCH, id);
+                }
                 break;
             }
         }
@@ -994,15 +1110,55 @@
     mManager->removeProvider(mProviderName);
 }
 
+status_t CameraProviderManager::ProviderInfo::setUpVendorTags() {
+    if (mVendorTagDescriptor != nullptr)
+        return OK;
+
+    hardware::hidl_vec<VendorTagSection> vts;
+    Status status;
+    hardware::Return<void> ret;
+    const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    ret = interface->getVendorTags(
+        [&](auto s, const auto& vendorTagSecs) {
+            status = s;
+            if (s == Status::OK) {
+                vts = vendorTagSecs;
+            }
+    });
+    if (!ret.isOk()) {
+        ALOGE("%s: Transaction error getting vendor tags from provider '%s': %s",
+                __FUNCTION__, mProviderName.c_str(), ret.description().c_str());
+        return DEAD_OBJECT;
+    }
+    if (status != Status::OK) {
+        return mapToStatusT(status);
+    }
+
+    // Read all vendor tag definitions into a descriptor
+    status_t res;
+    if ((res = HidlVendorTagDescriptor::createDescriptorFromHidl(vts, /*out*/mVendorTagDescriptor))
+            != OK) {
+        ALOGE("%s: Could not generate descriptor from vendor tag operations,"
+                "received error %s (%d). Camera clients will not be able to use"
+                "vendor tags", __FUNCTION__, strerror(res), res);
+        return res;
+    }
+
+    return OK;
+}
+
 template<class DeviceInfoT>
 std::unique_ptr<CameraProviderManager::ProviderInfo::DeviceInfo>
     CameraProviderManager::ProviderInfo::initializeDeviceInfo(
         const std::string &name, const metadata_vendor_id_t tagId,
-        const std::string &id, uint16_t minorVersion) const {
+        const std::string &id, uint16_t minorVersion) {
     Status status;
 
     auto cameraInterface =
-            getDeviceInterface<typename DeviceInfoT::InterfaceT>(name);
+            startDeviceInterface<typename DeviceInfoT::InterfaceT>(name);
     if (cameraInterface == nullptr) return nullptr;
 
     CameraResourceCost resourceCost;
@@ -1029,13 +1185,13 @@
     }
 
     return std::unique_ptr<DeviceInfo>(
-        new DeviceInfoT(name, tagId, id, minorVersion, resourceCost,
+        new DeviceInfoT(name, tagId, id, minorVersion, resourceCost, this,
                 mProviderPublicCameraIds, cameraInterface));
 }
 
 template<class InterfaceT>
 sp<InterfaceT>
-CameraProviderManager::ProviderInfo::getDeviceInterface(const std::string &name) const {
+CameraProviderManager::ProviderInfo::startDeviceInterface(const std::string &name) {
     ALOGE("%s: Device %s: Unknown HIDL device HAL major version %d:", __FUNCTION__,
             name.c_str(), InterfaceT::version.get_major());
     return nullptr;
@@ -1043,12 +1199,16 @@
 
 template<>
 sp<device::V1_0::ICameraDevice>
-CameraProviderManager::ProviderInfo::getDeviceInterface
-        <device::V1_0::ICameraDevice>(const std::string &name) const {
+CameraProviderManager::ProviderInfo::startDeviceInterface
+        <device::V1_0::ICameraDevice>(const std::string &name) {
     Status status;
     sp<device::V1_0::ICameraDevice> cameraInterface;
     hardware::Return<void> ret;
-    ret = mInterface->getCameraDeviceInterface_V1_x(name, [&status, &cameraInterface](
+    const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
+    if (interface == nullptr) {
+        return nullptr;
+    }
+    ret = interface->getCameraDeviceInterface_V1_x(name, [&status, &cameraInterface](
         Status s, sp<device::V1_0::ICameraDevice> interface) {
                 status = s;
                 cameraInterface = interface;
@@ -1068,12 +1228,16 @@
 
 template<>
 sp<device::V3_2::ICameraDevice>
-CameraProviderManager::ProviderInfo::getDeviceInterface
-        <device::V3_2::ICameraDevice>(const std::string &name) const {
+CameraProviderManager::ProviderInfo::startDeviceInterface
+        <device::V3_2::ICameraDevice>(const std::string &name) {
     Status status;
     sp<device::V3_2::ICameraDevice> cameraInterface;
     hardware::Return<void> ret;
-    ret = mInterface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
+    const sp<provider::V2_4::ICameraProvider> interface = startProviderInterface();
+    if (interface == nullptr) {
+        return nullptr;
+    }
+    ret = interface->getCameraDeviceInterface_V3_x(name, [&status, &cameraInterface](
         Status s, sp<device::V3_2::ICameraDevice> interface) {
                 status = s;
                 cameraInterface = interface;
@@ -1094,6 +1258,18 @@
 CameraProviderManager::ProviderInfo::DeviceInfo::~DeviceInfo() {}
 
 template<class InterfaceT>
+sp<InterfaceT> CameraProviderManager::ProviderInfo::DeviceInfo::startDeviceInterface() {
+    sp<InterfaceT> device;
+    ATRACE_CALL();
+    if (mSavedInterface == nullptr) {
+        device = mParentProvider->startDeviceInterface<InterfaceT>(mName);
+    } else {
+        device = (InterfaceT *) mSavedInterface.get();
+    }
+    return device;
+}
+
+template<class InterfaceT>
 status_t CameraProviderManager::ProviderInfo::DeviceInfo::setTorchMode(InterfaceT& interface,
         bool enabled) {
     Status s = interface->setTorchMode(enabled ? TorchMode::ON : TorchMode::OFF);
@@ -1104,31 +1280,31 @@
         const metadata_vendor_id_t tagId, const std::string &id,
         uint16_t minorVersion,
         const CameraResourceCost& resourceCost,
+        sp<ProviderInfo> parentProvider,
         const std::vector<std::string>& publicCameraIds,
         sp<InterfaceT> interface) :
         DeviceInfo(name, tagId, id, hardware::hidl_version{1, minorVersion},
-                   publicCameraIds, resourceCost),
-        mInterface(interface) {
+                   publicCameraIds, resourceCost, parentProvider) {
     // Get default parameters and initialize flash unit availability
     // Requires powering on the camera device
-    hardware::Return<Status> status = mInterface->open(nullptr);
+    hardware::Return<Status> status = interface->open(nullptr);
     if (!status.isOk()) {
         ALOGE("%s: Transaction error opening camera device %s to check for a flash unit: %s",
-                __FUNCTION__, mId.c_str(), status.description().c_str());
+                __FUNCTION__, id.c_str(), status.description().c_str());
         return;
     }
     if (status != Status::OK) {
         ALOGE("%s: Unable to open camera device %s to check for a flash unit: %s", __FUNCTION__,
-                mId.c_str(), CameraProviderManager::statusToString(status));
+                id.c_str(), CameraProviderManager::statusToString(status));
         return;
     }
     hardware::Return<void> ret;
-    ret = mInterface->getParameters([this](const hardware::hidl_string& parms) {
+    ret = interface->getParameters([this](const hardware::hidl_string& parms) {
                 mDefaultParameters.unflatten(String8(parms.c_str()));
             });
     if (!ret.isOk()) {
         ALOGE("%s: Transaction error reading camera device %s params to check for a flash unit: %s",
-                __FUNCTION__, mId.c_str(), status.description().c_str());
+                __FUNCTION__, id.c_str(), status.description().c_str());
         return;
     }
     const char *flashMode =
@@ -1137,27 +1313,43 @@
         mHasFlashUnit = true;
     }
 
-    ret = mInterface->close();
+    status_t res = cacheCameraInfo(interface);
+    if (res != OK) {
+        ALOGE("%s: Could not cache CameraInfo", __FUNCTION__);
+        return;
+    }
+
+    ret = interface->close();
     if (!ret.isOk()) {
         ALOGE("%s: Transaction error closing camera device %s after check for a flash unit: %s",
-                __FUNCTION__, mId.c_str(), status.description().c_str());
+                __FUNCTION__, id.c_str(), status.description().c_str());
+    }
+
+    if (!kEnableLazyHal) {
+        // Save HAL reference indefinitely
+        mSavedInterface = interface;
     }
 }
 
 CameraProviderManager::ProviderInfo::DeviceInfo1::~DeviceInfo1() {}
 
 status_t CameraProviderManager::ProviderInfo::DeviceInfo1::setTorchMode(bool enabled) {
-    return DeviceInfo::setTorchMode(mInterface, enabled);
+    return setTorchModeForDevice<InterfaceT>(enabled);
 }
 
 status_t CameraProviderManager::ProviderInfo::DeviceInfo1::getCameraInfo(
         hardware::CameraInfo *info) const {
     if (info == nullptr) return BAD_VALUE;
+    *info = mInfo;
+    return OK;
+}
 
+status_t CameraProviderManager::ProviderInfo::DeviceInfo1::cacheCameraInfo(
+        sp<CameraProviderManager::ProviderInfo::DeviceInfo1::InterfaceT> interface) {
     Status status;
     device::V1_0::CameraInfo cInfo;
     hardware::Return<void> ret;
-    ret = mInterface->getCameraInfo([&status, &cInfo](Status s, device::V1_0::CameraInfo camInfo) {
+    ret = interface->getCameraInfo([&status, &cInfo](Status s, device::V1_0::CameraInfo camInfo) {
                 status = s;
                 cInfo = camInfo;
             });
@@ -1172,27 +1364,31 @@
 
     switch(cInfo.facing) {
         case device::V1_0::CameraFacing::BACK:
-            info->facing = hardware::CAMERA_FACING_BACK;
+            mInfo.facing = hardware::CAMERA_FACING_BACK;
             break;
         case device::V1_0::CameraFacing::EXTERNAL:
             // Map external to front for legacy API
         case device::V1_0::CameraFacing::FRONT:
-            info->facing = hardware::CAMERA_FACING_FRONT;
+            mInfo.facing = hardware::CAMERA_FACING_FRONT;
             break;
         default:
             ALOGW("%s: Device %s: Unknown camera facing: %d",
                     __FUNCTION__, mId.c_str(), cInfo.facing);
-            info->facing = hardware::CAMERA_FACING_BACK;
+            mInfo.facing = hardware::CAMERA_FACING_BACK;
     }
-    info->orientation = cInfo.orientation;
+    mInfo.orientation = cInfo.orientation;
 
     return OK;
 }
 
-status_t CameraProviderManager::ProviderInfo::DeviceInfo1::dumpState(int fd) const {
+status_t CameraProviderManager::ProviderInfo::DeviceInfo1::dumpState(int fd) {
     native_handle_t* handle = native_handle_create(1,0);
     handle->data[0] = fd;
-    hardware::Return<Status> s = mInterface->dumpState(handle);
+    const sp<InterfaceT> interface = startDeviceInterface<InterfaceT>();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    hardware::Return<Status> s = interface->dumpState(handle);
     native_handle_delete(handle);
     if (!s.isOk()) {
         return INVALID_OPERATION;
@@ -1204,15 +1400,15 @@
         const metadata_vendor_id_t tagId, const std::string &id,
         uint16_t minorVersion,
         const CameraResourceCost& resourceCost,
+        sp<ProviderInfo> parentProvider,
         const std::vector<std::string>& publicCameraIds,
         sp<InterfaceT> interface) :
         DeviceInfo(name, tagId, id, hardware::hidl_version{3, minorVersion},
-                   publicCameraIds, resourceCost),
-        mInterface(interface) {
+                   publicCameraIds, resourceCost, parentProvider) {
     // Get camera characteristics and initialize flash unit availability
     Status status;
     hardware::Return<void> ret;
-    ret = mInterface->getCameraCharacteristics([&status, this](Status s,
+    ret = interface->getCameraCharacteristics([&status, this](Status s,
                     device::V3_2::CameraMetadata metadata) {
                 status = s;
                 if (s == Status::OK) {
@@ -1231,13 +1427,13 @@
             });
     if (!ret.isOk()) {
         ALOGE("%s: Transaction error getting camera characteristics for device %s"
-                " to check for a flash unit: %s", __FUNCTION__, mId.c_str(),
+                " to check for a flash unit: %s", __FUNCTION__, id.c_str(),
                 ret.description().c_str());
         return;
     }
     if (status != Status::OK) {
         ALOGE("%s: Unable to get camera characteristics for device %s: %s (%d)",
-                __FUNCTION__, mId.c_str(), CameraProviderManager::statusToString(status), status);
+                __FUNCTION__, id.c_str(), CameraProviderManager::statusToString(status), status);
         return;
     }
     status_t res = fixupMonochromeTags();
@@ -1257,12 +1453,12 @@
 
     queryPhysicalCameraIds();
     // Get physical camera characteristics if applicable
-    auto castResult = device::V3_5::ICameraDevice::castFrom(mInterface);
+    auto castResult = device::V3_5::ICameraDevice::castFrom(interface);
     if (!castResult.isOk()) {
         ALOGV("%s: Unable to convert ICameraDevice instance to version 3.5", __FUNCTION__);
         return;
     }
-    sp<hardware::camera::device::V3_5::ICameraDevice> interface_3_5 = castResult;
+    sp<device::V3_5::ICameraDevice> interface_3_5 = castResult;
     if (interface_3_5 == nullptr) {
         ALOGE("%s: Converted ICameraDevice instance to nullptr", __FUNCTION__);
         return;
@@ -1296,7 +1492,7 @@
 
             if (!ret.isOk()) {
                 ALOGE("%s: Transaction error getting physical camera %s characteristics for %s: %s",
-                        __FUNCTION__, id.c_str(), mId.c_str(), ret.description().c_str());
+                        __FUNCTION__, id.c_str(), id.c_str(), ret.description().c_str());
                 return;
             }
             if (status != Status::OK) {
@@ -1307,12 +1503,17 @@
             }
         }
     }
+
+    if (!kEnableLazyHal) {
+        // Save HAL reference indefinitely
+        mSavedInterface = interface;
+    }
 }
 
 CameraProviderManager::ProviderInfo::DeviceInfo3::~DeviceInfo3() {}
 
 status_t CameraProviderManager::ProviderInfo::DeviceInfo3::setTorchMode(bool enabled) {
-    return DeviceInfo::setTorchMode(mInterface, enabled);
+    return setTorchModeForDevice<InterfaceT>(enabled);
 }
 
 status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraInfo(
@@ -1363,10 +1564,14 @@
     return isBackwardCompatible;
 }
 
-status_t CameraProviderManager::ProviderInfo::DeviceInfo3::dumpState(int fd) const {
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::dumpState(int fd) {
     native_handle_t* handle = native_handle_create(1,0);
     handle->data[0] = fd;
-    auto ret = mInterface->dumpState(handle);
+    const sp<InterfaceT> interface = startDeviceInterface<InterfaceT>();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    auto ret = interface->dumpState(handle);
     native_handle_delete(handle);
     if (!ret.isOk()) {
         return INVALID_OPERATION;
@@ -1396,8 +1601,14 @@
 
 status_t CameraProviderManager::ProviderInfo::DeviceInfo3::isSessionConfigurationSupported(
         const hardware::camera::device::V3_4::StreamConfiguration &configuration,
-        bool *status /*out*/) const {
-    auto castResult = device::V3_5::ICameraDevice::castFrom(mInterface);
+        bool *status /*out*/) {
+
+    const sp<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT> interface =
+            this->startDeviceInterface<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
+    if (interface == nullptr) {
+        return DEAD_OBJECT;
+    }
+    auto castResult = device::V3_5::ICameraDevice::castFrom(interface);
     sp<hardware::camera::device::V3_5::ICameraDevice> interface_3_5 = castResult;
     if (interface_3_5 == nullptr) {
         return INVALID_OPERATION;
@@ -1673,7 +1884,7 @@
 
 
 status_t HidlVendorTagDescriptor::createDescriptorFromHidl(
-        const hardware::hidl_vec<hardware::camera::common::V1_0::VendorTagSection>& vts,
+        const hardware::hidl_vec<common::V1_0::VendorTagSection>& vts,
         /*out*/
         sp<VendorTagDescriptor>& descriptor) {
 
@@ -1701,7 +1912,7 @@
 
     int idx = 0;
     for (size_t s = 0; s < vts.size(); s++) {
-        const hardware::camera::common::V1_0::VendorTagSection& section = vts[s];
+        const common::V1_0::VendorTagSection& section = vts[s];
         const char *sectionName = section.sectionName.c_str();
         if (sectionName == NULL) {
             ALOGE("%s: no section name defined for vendor tag section %zu.", __FUNCTION__, s);
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index 99b87fb..0966743 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -18,6 +18,7 @@
 #define ANDROID_SERVERS_CAMERA_CAMERAPROVIDER_H
 
 #include <vector>
+#include <unordered_map>
 #include <unordered_set>
 #include <string>
 #include <mutex>
@@ -111,6 +112,14 @@
     };
 
     /**
+     * Represents the mode a camera device is currently in
+     */
+    enum class DeviceMode {
+        TORCH,
+        CAMERA
+    };
+
+    /**
      * Initialize the manager and give it a status listener; optionally accepts a service
      * interaction proxy.
      *
@@ -182,7 +191,7 @@
     /**
      * Check if a given camera device support setTorchMode API.
      */
-    bool supportSetTorchMode(const std::string &id);
+    bool supportSetTorchMode(const std::string &id) const;
 
     /**
      * Turn on or off the flashlight on a given camera device.
@@ -213,6 +222,17 @@
             sp<hardware::camera::device::V1_0::ICameraDevice> *session);
 
     /**
+     * Save the ICameraProvider while it is being used by a camera or torch client
+     */
+    void saveRef(DeviceMode usageType, const std::string &cameraId,
+            sp<hardware::camera::provider::V2_4::ICameraProvider> provider);
+
+    /**
+     * Notify that the camera or torch is no longer being used by a camera client
+     */
+    void removeRef(DeviceMode usageType, const std::string &cameraId);
+
+    /**
      * IServiceNotification::onRegistration
      * Invoked by the hardware service manager when a new camera provider is registered
      */
@@ -259,20 +279,43 @@
 
     static HardwareServiceInteractionProxy sHardwareServiceInteractionProxy;
 
+    // Mapping from CameraDevice IDs to CameraProviders. This map is used to keep the
+    // ICameraProvider alive while it is in use by the camera with the given ID for camera
+    // capabilities
+    std::unordered_map<std::string, sp<hardware::camera::provider::V2_4::ICameraProvider>>
+            mCameraProviderByCameraId;
+
+    // Mapping from CameraDevice IDs to CameraProviders. This map is used to keep the
+    // ICameraProvider alive while it is in use by the camera with the given ID for torch
+    // capabilities
+    std::unordered_map<std::string, sp<hardware::camera::provider::V2_4::ICameraProvider>>
+            mTorchProviderByCameraId;
+
+    // Lock for accessing mCameraProviderByCameraId and mTorchProviderByCameraId
+    std::mutex mProviderInterfaceMapLock;
+
     struct ProviderInfo :
             virtual public hardware::camera::provider::V2_4::ICameraProviderCallback,
             virtual public hardware::hidl_death_recipient
     {
         const std::string mProviderName;
-        const sp<hardware::camera::provider::V2_4::ICameraProvider> mInterface;
         const metadata_vendor_id_t mProviderTagid;
+        sp<VendorTagDescriptor> mVendorTagDescriptor;
+        bool mSetTorchModeSupported;
+        bool mIsRemote;
+
+        // This pointer is used to keep a reference to the ICameraProvider that was last accessed.
+        wp<hardware::camera::provider::V2_4::ICameraProvider> mActiveInterface;
+
+        sp<hardware::camera::provider::V2_4::ICameraProvider> mSavedInterface;
 
         ProviderInfo(const std::string &providerName,
-                sp<hardware::camera::provider::V2_4::ICameraProvider>& interface,
                 CameraProviderManager *manager);
         ~ProviderInfo();
 
-        status_t initialize();
+        status_t initialize(sp<hardware::camera::provider::V2_4::ICameraProvider>& interface);
+
+        const sp<hardware::camera::provider::V2_4::ICameraProvider> startProviderInterface();
 
         const std::string& getType() const;
 
@@ -294,6 +337,11 @@
         // hidl_death_recipient interface - this locks the parent mInterfaceMutex
         virtual void serviceDied(uint64_t cookie, const wp<hidl::base::V1_0::IBase>& who) override;
 
+        /**
+         * Setup vendor tags for this provider
+         */
+        status_t setUpVendorTags();
+
         // Basic device information, common to all camera devices
         struct DeviceInfo {
             const std::string mName;  // Full instance name
@@ -302,16 +350,20 @@
             const metadata_vendor_id_t mProviderTagid;
             bool mIsLogicalCamera;
             std::vector<std::string> mPhysicalIds;
+            hardware::CameraInfo mInfo;
+            sp<IBase> mSavedInterface;
 
             const hardware::camera::common::V1_0::CameraResourceCost mResourceCost;
 
             hardware::camera::common::V1_0::CameraDeviceStatus mStatus;
 
+            sp<ProviderInfo> mParentProvider;
+
             bool hasFlashUnit() const { return mHasFlashUnit; }
             virtual status_t setTorchMode(bool enabled) = 0;
             virtual status_t getCameraInfo(hardware::CameraInfo *info) const = 0;
             virtual bool isAPI1Compatible() const = 0;
-            virtual status_t dumpState(int fd) const = 0;
+            virtual status_t dumpState(int fd) = 0;
             virtual status_t getCameraCharacteristics(CameraMetadata *characteristics) const {
                 (void) characteristics;
                 return INVALID_OPERATION;
@@ -325,19 +377,23 @@
 
             virtual status_t isSessionConfigurationSupported(
                     const hardware::camera::device::V3_4::StreamConfiguration &/*configuration*/,
-                    bool * /*status*/)
-                    const {
+                    bool * /*status*/) {
                 return INVALID_OPERATION;
             }
 
+            template<class InterfaceT>
+            sp<InterfaceT> startDeviceInterface();
+
             DeviceInfo(const std::string& name, const metadata_vendor_id_t tagId,
                     const std::string &id, const hardware::hidl_version& version,
                     const std::vector<std::string>& publicCameraIds,
-                    const hardware::camera::common::V1_0::CameraResourceCost& resourceCost) :
+                    const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
+                    sp<ProviderInfo> parentProvider) :
                     mName(name), mId(id), mVersion(version), mProviderTagid(tagId),
                     mIsLogicalCamera(false), mResourceCost(resourceCost),
                     mStatus(hardware::camera::common::V1_0::CameraDeviceStatus::PRESENT),
-                    mHasFlashUnit(false), mPublicCameraIds(publicCameraIds) {}
+                    mParentProvider(parentProvider), mHasFlashUnit(false),
+                    mPublicCameraIds(publicCameraIds) {}
             virtual ~DeviceInfo();
         protected:
             bool mHasFlashUnit;
@@ -345,6 +401,14 @@
 
             template<class InterfaceT>
             static status_t setTorchMode(InterfaceT& interface, bool enabled);
+
+            template<class InterfaceT>
+            status_t setTorchModeForDevice(bool enabled) {
+                // Don't save the ICameraProvider interface here because we assume that this was
+                // called from CameraProviderManager::setTorchMode(), which does save it.
+                const sp<InterfaceT> interface = startDeviceInterface<InterfaceT>();
+                return DeviceInfo::setTorchMode(interface, enabled);
+            }
         };
         std::vector<std::unique_ptr<DeviceInfo>> mDevices;
         std::unordered_set<std::string> mUniqueCameraIds;
@@ -360,32 +424,32 @@
         // HALv1-specific camera fields, including the actual device interface
         struct DeviceInfo1 : public DeviceInfo {
             typedef hardware::camera::device::V1_0::ICameraDevice InterfaceT;
-            const sp<InterfaceT> mInterface;
 
             virtual status_t setTorchMode(bool enabled) override;
             virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
             //In case of Device1Info assume that we are always API1 compatible
             virtual bool isAPI1Compatible() const override { return true; }
-            virtual status_t dumpState(int fd) const override;
+            virtual status_t dumpState(int fd) override;
             DeviceInfo1(const std::string& name, const metadata_vendor_id_t tagId,
                     const std::string &id, uint16_t minorVersion,
                     const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
+                    sp<ProviderInfo> parentProvider,
                     const std::vector<std::string>& publicCameraIds,
                     sp<InterfaceT> interface);
             virtual ~DeviceInfo1();
         private:
             CameraParameters2 mDefaultParameters;
+            status_t cacheCameraInfo(sp<InterfaceT> interface);
         };
 
         // HALv3-specific camera fields, including the actual device interface
         struct DeviceInfo3 : public DeviceInfo {
             typedef hardware::camera::device::V3_2::ICameraDevice InterfaceT;
-            const sp<InterfaceT> mInterface;
 
             virtual status_t setTorchMode(bool enabled) override;
             virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
             virtual bool isAPI1Compatible() const override;
-            virtual status_t dumpState(int fd) const override;
+            virtual status_t dumpState(int fd) override;
             virtual status_t getCameraCharacteristics(
                     CameraMetadata *characteristics) const override;
             virtual status_t getPhysicalCameraCharacteristics(const std::string& physicalCameraId,
@@ -393,11 +457,12 @@
             virtual status_t isSessionConfigurationSupported(
                     const hardware::camera::device::V3_4::StreamConfiguration &configuration,
                     bool *status /*out*/)
-                    const override;
+                    override;
 
             DeviceInfo3(const std::string& name, const metadata_vendor_id_t tagId,
                     const std::string &id, uint16_t minorVersion,
                     const hardware::camera::common::V1_0::CameraResourceCost& resourceCost,
+                    sp<ProviderInfo> parentProvider,
                     const std::vector<std::string>& publicCameraIds, sp<InterfaceT> interface);
             virtual ~DeviceInfo3();
         private:
@@ -424,11 +489,11 @@
         template<class DeviceInfoT>
         std::unique_ptr<DeviceInfo> initializeDeviceInfo(const std::string &name,
                 const metadata_vendor_id_t tagId, const std::string &id,
-                uint16_t minorVersion) const;
+                uint16_t minorVersion);
 
         // Helper for initializeDeviceInfo to use the right CameraProvider get method.
         template<class InterfaceT>
-        sp<InterfaceT> getDeviceInterface(const std::string &name) const;
+        sp<InterfaceT> startDeviceInterface(const std::string &name);
 
         // Parse provider instance name for type and id
         static status_t parseProviderName(const std::string& name,
@@ -462,6 +527,14 @@
 
     std::vector<sp<ProviderInfo>> mProviders;
 
+    void addProviderToMap(
+            const std::string &cameraId,
+            sp<hardware::camera::provider::V2_4::ICameraProvider> provider,
+            bool isTorchUsage);
+    void removeCameraIdFromMap(
+        std::unordered_map<std::string, sp<hardware::camera::provider::V2_4::ICameraProvider>> &map,
+        const std::string &cameraId);
+
     static const char* deviceStatusToString(
         const hardware::camera::common::V1_0::CameraDeviceStatus&);
     static const char* torchStatusToString(
diff --git a/services/mediacodec/registrant/Android.bp b/services/mediacodec/registrant/Android.bp
new file mode 100644
index 0000000..653317b
--- /dev/null
+++ b/services/mediacodec/registrant/Android.bp
@@ -0,0 +1,53 @@
+cc_library_shared {
+    name: "libmedia_codecserviceregistrant",
+    srcs: [
+        "CodecServiceRegistrant.cpp",
+    ],
+
+    header_libs: [
+        "libmedia_headers",
+    ],
+
+    shared_libs: [
+        "android.hardware.media.c2@1.0",
+        "libbase",
+        "libcodec2_hidl@1.0",
+        "libcodec2_vndk",
+        "libutils",
+    ],
+
+    // Codecs
+    runtime_libs: [
+        "libcodec2_soft_avcdec",
+        "libcodec2_soft_avcenc",
+        "libcodec2_soft_aacdec",
+        "libcodec2_soft_aacenc",
+        "libcodec2_soft_amrnbdec",
+        "libcodec2_soft_amrnbenc",
+        "libcodec2_soft_amrwbdec",
+        "libcodec2_soft_amrwbenc",
+        "libcodec2_soft_hevcdec",
+        "libcodec2_soft_g711alawdec",
+        "libcodec2_soft_g711mlawdec",
+        "libcodec2_soft_mpeg2dec",
+        "libcodec2_soft_h263dec",
+        "libcodec2_soft_h263enc",
+        "libcodec2_soft_mpeg4dec",
+        "libcodec2_soft_mpeg4enc",
+        "libcodec2_soft_mp3dec",
+        "libcodec2_soft_vorbisdec",
+        "libcodec2_soft_opusdec",
+        "libcodec2_soft_vp8dec",
+        "libcodec2_soft_vp9dec",
+        "libcodec2_soft_vp8enc",
+        "libcodec2_soft_vp9enc",
+        "libcodec2_soft_rawdec",
+        "libcodec2_soft_flacdec",
+        "libcodec2_soft_flacenc",
+        "libcodec2_soft_gsmdec",
+        "libcodec2_soft_xaacdec",
+    ],
+
+    compile_multilib: "32",
+}
+
diff --git a/media/codec2/hidl/services/C2SoftwareCodecServiceRegistrant.cpp b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
similarity index 74%
rename from media/codec2/hidl/services/C2SoftwareCodecServiceRegistrant.cpp
rename to services/mediacodec/registrant/CodecServiceRegistrant.cpp
index e10ae6e..706ebee 100644
--- a/media/codec2/hidl/services/C2SoftwareCodecServiceRegistrant.cpp
+++ b/services/mediacodec/registrant/CodecServiceRegistrant.cpp
@@ -15,26 +15,30 @@
  */
 
 //#define LOG_NDEBUG 0
-#define LOG_TAG "C2SoftwareCodecServiceRegistrant"
+#define LOG_TAG "CodecServiceRegistrant"
+
+#include <android-base/logging.h>
 
 #include <C2PlatformSupport.h>
 #include <codec2/hidl/1.0/ComponentStore.h>
 #include <media/CodecServiceRegistrant.h>
-#include <log/log.h>
 
 extern "C" void RegisterCodecServices() {
     using namespace ::android::hardware::media::c2::V1_0;
+    LOG(INFO) << "Creating software Codec2 service...";
     android::sp<IComponentStore> store =
         new utils::ComponentStore(
                 android::GetCodec2PlatformComponentStore());
     if (store == nullptr) {
-        ALOGE("Cannot create Codec2's IComponentStore software service.");
+        LOG(ERROR) <<
+                "Cannot create software Codec2 service.";
     } else {
         if (store->registerAsService("software") != android::OK) {
-            ALOGE("Cannot register Codec2's "
-                    "IComponentStore software service.");
+            LOG(ERROR) <<
+                    "Cannot register software Codec2 service.";
         } else {
-            ALOGI("Codec2's IComponentStore software service created.");
+            LOG(INFO) <<
+                    "Software Codec2 service created.";
         }
     }
 }