Merge "Camera: Add onCameraOpened/onCameraClosed callbacks" into rvc-dev
diff --git a/media/codec2/components/vorbis/Android.bp b/media/codec2/components/vorbis/Android.bp
index a5f485d..bc1c380 100644
--- a/media/codec2/components/vorbis/Android.bp
+++ b/media/codec2/components/vorbis/Android.bp
@@ -7,5 +7,5 @@
 
     srcs: ["C2SoftVorbisDec.cpp"],
 
-    shared_libs: ["libvorbisidec"],
+    static_libs: ["libvorbisidec"],
 }
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
index 9656eb4..20f4665 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioDecTest.cpp
@@ -71,7 +71,8 @@
         mDisableTest = false;
         ALOGV("Codec2AudioDecHidlTest SetUp");
         mClient = android::Codec2Client::CreateFromService(
-            gEnv->getInstance().c_str());
+            gEnv->getInstance().c_str(),
+            !bool(android::Codec2Client::CreateFromService("default", true)));
         ASSERT_NE(mClient, nullptr);
         mListener.reset(new CodecListener(
             [this](std::list<std::unique_ptr<C2Work>>& workItems) {
diff --git a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
index 01baf7e..ab6bfb2 100644
--- a/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/audio/VtsHalMediaC2V1_0TargetAudioEncTest.cpp
@@ -65,7 +65,8 @@
         mDisableTest = false;
         ALOGV("Codec2AudioEncHidlTest SetUp");
         mClient = android::Codec2Client::CreateFromService(
-            gEnv->getInstance().c_str());
+            gEnv->getInstance().c_str(),
+            !bool(android::Codec2Client::CreateFromService("default", true)));
         ASSERT_NE(mClient, nullptr);
         mListener.reset(new CodecListener(
             [this](std::list<std::unique_ptr<C2Work>>& workItems) {
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
index 9404aa8..256603c 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoDecTest.cpp
@@ -78,7 +78,8 @@
         mDisableTest = false;
         ALOGV("Codec2VideoDecHidlTest SetUp");
         mClient = android::Codec2Client::CreateFromService(
-            gEnv->getInstance().c_str());
+            gEnv->getInstance().c_str(),
+            !bool(android::Codec2Client::CreateFromService("default", true)));
         ASSERT_NE(mClient, nullptr);
         mListener.reset(new CodecListener(
             [this](std::list<std::unique_ptr<C2Work>>& workItems) {
diff --git a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
index c1f5a92..15f6acd 100644
--- a/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
+++ b/media/codec2/hidl/1.0/vts/functional/video/VtsHalMediaC2V1_0TargetVideoEncTest.cpp
@@ -64,7 +64,8 @@
         mDisableTest = false;
         ALOGV("Codec2VideoEncHidlTest SetUp");
         mClient = android::Codec2Client::CreateFromService(
-            gEnv->getInstance().c_str());
+            gEnv->getInstance().c_str(),
+            !bool(android::Codec2Client::CreateFromService("default", true)));
         ASSERT_NE(mClient, nullptr);
         mListener.reset(new CodecListener(
             [this](std::list<std::unique_ptr<C2Work>>& workItems) {
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 199a99c..49b49a4 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -93,6 +93,69 @@
     return i;
 }
 
+class Client2Store : public C2ComponentStore {
+    std::shared_ptr<Codec2Client> mClient;
+
+public:
+    Client2Store(std::shared_ptr<Codec2Client> const& client)
+        : mClient(client) { }
+
+    virtual ~Client2Store() = default;
+
+    virtual c2_status_t config_sm(
+            std::vector<C2Param*> const &params,
+            std::vector<std::unique_ptr<C2SettingResult>>* const failures) {
+        return mClient->config(params, C2_MAY_BLOCK, failures);
+    };
+
+    virtual c2_status_t copyBuffer(
+            std::shared_ptr<C2GraphicBuffer>,
+            std::shared_ptr<C2GraphicBuffer>) {
+        return C2_OMITTED;
+    }
+
+    virtual c2_status_t createComponent(
+            C2String, std::shared_ptr<C2Component>* const component) {
+        component->reset();
+        return C2_OMITTED;
+    }
+
+    virtual c2_status_t createInterface(
+            C2String, std::shared_ptr<C2ComponentInterface>* const interface) {
+        interface->reset();
+        return C2_OMITTED;
+    }
+
+    virtual c2_status_t query_sm(
+            std::vector<C2Param*> const& stackParams,
+            std::vector<C2Param::Index> const& heapParamIndices,
+            std::vector<std::unique_ptr<C2Param>>* const heapParams) const {
+        return mClient->query(stackParams, heapParamIndices, C2_MAY_BLOCK, heapParams);
+    }
+
+    virtual c2_status_t querySupportedParams_nb(
+            std::vector<std::shared_ptr<C2ParamDescriptor>>* const params) const {
+        return mClient->querySupportedParams(params);
+    }
+
+    virtual c2_status_t querySupportedValues_sm(
+            std::vector<C2FieldSupportedValuesQuery>& fields) const {
+        return mClient->querySupportedValues(fields, C2_MAY_BLOCK);
+    }
+
+    virtual C2String getName() const {
+        return mClient->getName();
+    }
+
+    virtual std::shared_ptr<C2ParamReflector> getParamReflector() const {
+        return mClient->getParamReflector();
+    }
+
+    virtual std::vector<std::shared_ptr<C2Component::Traits const>> listComponents() {
+        return std::vector<std::shared_ptr<C2Component::Traits const>>();
+    }
+};
+
 }  // unnamed namespace
 
 // This class caches a Codec2Client object and its component traits. The client
@@ -850,10 +913,24 @@
 }
 
 std::shared_ptr<Codec2Client> Codec2Client::CreateFromService(
-        const char* name) {
+        const char* name,
+        bool setAsPreferredCodec2ComponentStore) {
     size_t index = getServiceIndex(name);
-    return index == GetServiceNames().size() ?
-            nullptr : _CreateFromIndex(index);
+    if (index == GetServiceNames().size()) {
+        if (setAsPreferredCodec2ComponentStore) {
+            LOG(WARNING) << "CreateFromService(" << name
+                         << ") -- preferred C2ComponentStore not set.";
+        }
+        return nullptr;
+    }
+    std::shared_ptr<Codec2Client> client = _CreateFromIndex(index);
+    if (setAsPreferredCodec2ComponentStore) {
+        SetPreferredCodec2ComponentStore(
+                std::make_shared<Client2Store>(client));
+        LOG(INFO) << "CreateFromService(" << name
+                  << ") -- service set as preferred C2ComponentStore.";
+    }
+    return client;
 }
 
 std::vector<std::shared_ptr<Codec2Client>> Codec2Client::
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index 649dffd..ffd194a 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -184,8 +184,15 @@
     // Note: A software service will have "_software" as a suffix.
     static std::vector<std::string> const& GetServiceNames();
 
-    // Create a service with a given service name.
-    static std::shared_ptr<Codec2Client> CreateFromService(char const* name);
+    // Create a client to a service with a given name.
+    //
+    // After a client to the service is successfully created, if
+    // setAsPreferredCodec2ComponentStore is true, the component store that the
+    // service hosts will be set as the preferred C2ComponentStore for this
+    // process. (See SetPreferredCodec2ComponentStore() for more information.)
+    static std::shared_ptr<Codec2Client> CreateFromService(
+            char const* name,
+            bool setAsPreferredCodec2ComponentStore = false);
 
     // Get clients to all services.
     static std::vector<std::shared_ptr<Codec2Client>> CreateFromAllServices();
diff --git a/media/codec2/sfplugin/CCodec.cpp b/media/codec2/sfplugin/CCodec.cpp
index 0d093da..cc132de 100644
--- a/media/codec2/sfplugin/CCodec.cpp
+++ b/media/codec2/sfplugin/CCodec.cpp
@@ -1320,7 +1320,8 @@
         Mutexed<std::unique_ptr<Config>>::Locked configLocked(mConfig);
         const std::unique_ptr<Config> &config = *configLocked;
         inputFormat = config->mInputFormat;
-        outputFormat = config->mOutputFormat;
+        // start triggers format dup
+        outputFormat = config->mOutputFormat = config->mOutputFormat->dup();
         if (config->mInputSurface) {
             err2 = config->mInputSurface->start();
         }
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index b869bd9..e85e73a 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1251,7 +1251,7 @@
         } else {
             output->buffers.reset(new LinearOutputBuffers(mName));
         }
-        output->buffers->setFormat(outputFormat->dup());
+        output->buffers->setFormat(outputFormat);
 
 
         // Try to set output surface to created block pool if given.
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 2f67a18..f030ab0 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -792,6 +792,13 @@
 
 // ---------------------------------------------------------------------------
 
+void AudioSystem::onNewAudioModulesAvailable()
+{
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+    if (aps == 0) return;
+    aps->onNewAudioModulesAvailable();
+}
+
 status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
                                                audio_policy_dev_state_t state,
                                                const char *device_address,
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index cccb131..f1213a3 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -113,6 +113,7 @@
     REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
     GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY,
     GET_DEVICES_FOR_ATTRIBUTES,
+    AUDIO_MODULES_UPDATED,  // oneway
 };
 
 #define MAX_ITEMS_PER_LIST 1024
@@ -1451,6 +1452,13 @@
         }
         return NO_ERROR;
     }
+
+    virtual void onNewAudioModulesAvailable()
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+        remote()->transact(AUDIO_MODULES_UPDATED, data, &reply, IBinder::FLAG_ONEWAY);
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1522,7 +1530,8 @@
         case REMOVE_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
         case GET_PREFERRED_DEVICE_FOR_PRODUCT_STRATEGY:
         case GET_DEVICES_FOR_ATTRIBUTES:
-        case SET_ALLOWED_CAPTURE_POLICY: {
+        case SET_ALLOWED_CAPTURE_POLICY:
+        case AUDIO_MODULES_UPDATED: {
             if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
                 ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                       __func__, code, IPCThreadState::self()->getCallingPid(),
@@ -2672,6 +2681,12 @@
             return NO_ERROR;
         }
 
+        case AUDIO_MODULES_UPDATED: {
+            CHECK_INTERFACE(IAudioPolicyService, data, reply);
+            onNewAudioModulesAvailable();
+            return NO_ERROR;
+        } break;
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 07a2292..aebc875 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -221,6 +221,7 @@
     //
     // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
     //
+    static void onNewAudioModulesAvailable();
     static status_t setDeviceConnectionState(audio_devices_t device, audio_policy_dev_state_t state,
                                              const char *device_address, const char *device_name,
                                              audio_format_t encodedFormat);
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 779ca43..ec3461e 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -42,6 +42,7 @@
     //
     // IAudioPolicyService interface (see AudioPolicyInterface for method descriptions)
     //
+    virtual void onNewAudioModulesAvailable() = 0;
     virtual status_t setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
                                               const char *device_address,
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
index e6e9688..1c0eacb 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
@@ -15,12 +15,13 @@
  */
 
 #include <string.h>
-#include <vector>
+#include <set>
 
 #define LOG_TAG "DevicesFactoryHalHidl"
 //#define LOG_NDEBUG 0
 
 #include <android/hidl/manager/1.0/IServiceManager.h>
+#include <android/hidl/manager/1.0/IServiceNotification.h>
 #include PATH(android/hardware/audio/FILE_VERSION/IDevice.h)
 #include <media/audiohal/hidl/HalDeathHandler.h>
 #include <utils/Log.h>
@@ -29,33 +30,57 @@
 #include "DeviceHalHidl.h"
 #include "DevicesFactoryHalHidl.h"
 
-#include <set>
-
 using ::android::hardware::audio::CPP_VERSION::IDevice;
 using ::android::hardware::audio::CPP_VERSION::Result;
 using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hidl::manager::V1_0::IServiceManager;
+using ::android::hidl::manager::V1_0::IServiceNotification;
 
 namespace android {
 namespace CPP_VERSION {
 
-DevicesFactoryHalHidl::DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory) {
-    ALOG_ASSERT(devicesFactory != nullptr, "Provided IDevicesFactory service is NULL");
+class ServiceNotificationListener : public IServiceNotification {
+  public:
+    explicit ServiceNotificationListener(sp<DevicesFactoryHalHidl> factory)
+            : mFactory(factory) {}
 
-    mDeviceFactories.push_back(devicesFactory);
-    if (MAJOR_VERSION >= 4) {
-        // The MSD factory is optional and only available starting at HAL 4.0
-        sp<IDevicesFactory> msdFactory{IDevicesFactory::getService(AUDIO_HAL_SERVICE_NAME_MSD)};
-        if (msdFactory) {
-            mDeviceFactories.push_back(msdFactory);
+    Return<void> onRegistration(const hidl_string& /*fully_qualified_name*/,
+            const hidl_string& instance_name,
+            bool /*pre_existing*/) override {
+        if (static_cast<std::string>(instance_name) == "default") return Void();
+        sp<DevicesFactoryHalHidl> factory = mFactory.promote();
+        if (!factory) return Void();
+        sp<IDevicesFactory> halFactory = IDevicesFactory::getService(instance_name);
+        if (halFactory) {
+            factory->addDeviceFactory(halFactory, true /*needToNotify*/);
         }
+        return Void();
     }
-    for (const auto& factory : mDeviceFactories) {
-        // It is assumed that the DevicesFactoryHalInterface instance is owned
-        // by AudioFlinger and thus have the same lifespan.
-        factory->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
-    }
+
+  private:
+    wp<DevicesFactoryHalHidl> mFactory;
+};
+
+DevicesFactoryHalHidl::DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory) {
+    ALOG_ASSERT(devicesFactory != nullptr, "Provided default IDevicesFactory service is NULL");
+    addDeviceFactory(devicesFactory, false /*needToNotify*/);
 }
 
+void DevicesFactoryHalHidl::onFirstRef() {
+    sp<IServiceManager> sm = IServiceManager::getService();
+    ALOG_ASSERT(sm != nullptr, "Hardware service manager is not running");
+    sp<ServiceNotificationListener> listener = new ServiceNotificationListener(this);
+    Return<bool> result = sm->registerForNotifications(
+            IDevicesFactory::descriptor, "", listener);
+    if (result.isOk()) {
+        ALOGE_IF(!static_cast<bool>(result),
+                "Hardware service manager refused to register listener");
+    } else {
+        ALOGE("Failed to register for hardware service manager notifications: %s",
+                result.description().c_str());
+    }
+}
 
 #if MAJOR_VERSION == 2
 static IDevicesFactory::Device idFromHal(const char *name, status_t* status) {
@@ -83,12 +108,13 @@
 #endif
 
 status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
-    if (mDeviceFactories.empty()) return NO_INIT;
+    auto factories = copyDeviceFactories();
+    if (factories.empty()) return NO_INIT;
     status_t status;
     auto hidlId = idFromHal(name, &status);
     if (status != OK) return status;
     Result retval = Result::NOT_INITIALIZED;
-    for (const auto& factory : mDeviceFactories) {
+    for (const auto& factory : factories) {
         Return<void> ret = factory->openDevice(
                 hidlId,
                 [&](Result r, const sp<IDevice>& result) {
@@ -113,10 +139,9 @@
 
 status_t DevicesFactoryHalHidl::getHalPids(std::vector<pid_t> *pids) {
     std::set<pid_t> pidsSet;
-
-    for (const auto& factory : mDeviceFactories) {
+    auto factories = copyDeviceFactories();
+    for (const auto& factory : factories) {
         using ::android::hidl::base::V1_0::DebugInfo;
-        using android::hidl::manager::V1_0::IServiceManager;
 
         DebugInfo debugInfo;
         auto ret = factory->getDebugInfo([&] (const auto &info) {
@@ -135,5 +160,48 @@
     return NO_ERROR;
 }
 
+status_t DevicesFactoryHalHidl::setCallbackOnce(sp<DevicesFactoryHalCallback> callback) {
+    ALOG_ASSERT(callback != nullptr);
+    bool needToCallCallback = false;
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        if (mCallback.unsafe_get()) return INVALID_OPERATION;
+        mCallback = callback;
+        if (mHaveUndeliveredNotifications) {
+            needToCallCallback = true;
+            mHaveUndeliveredNotifications = false;
+        }
+    }
+    if (needToCallCallback) {
+        callback->onNewDevicesAvailable();
+    }
+    return NO_ERROR;
+}
+
+void DevicesFactoryHalHidl::addDeviceFactory(sp<IDevicesFactory> factory, bool needToNotify) {
+    // It is assumed that the DevicesFactoryHalInterface instance is owned
+    // by AudioFlinger and thus have the same lifespan.
+    factory->linkToDeath(HalDeathHandler::getInstance(), 0 /*cookie*/);
+    sp<DevicesFactoryHalCallback> callback;
+    {
+        std::lock_guard<std::mutex> lock(mLock);
+        mDeviceFactories.push_back(factory);
+        if (needToNotify) {
+            callback = mCallback.promote();
+            if (!callback) {
+                mHaveUndeliveredNotifications = true;
+            }
+        }
+    }
+    if (callback) {
+        callback->onNewDevicesAvailable();
+    }
+}
+
+std::vector<sp<IDevicesFactory>> DevicesFactoryHalHidl::copyDeviceFactories() {
+    std::lock_guard<std::mutex> lock(mLock);
+    return mDeviceFactories;
+}
+
 } // namespace CPP_VERSION
 } // namespace android
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHidl.h b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
index 52185c8..6f84efe 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHidl.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHidl.h
@@ -17,6 +17,9 @@
 #ifndef ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HIDL_H
 #define ANDROID_HARDWARE_DEVICES_FACTORY_HAL_HIDL_H
 
+#include <mutex>
+#include <vector>
+
 #include PATH(android/hardware/audio/FILE_VERSION/IDevicesFactory.h)
 #include <media/audiohal/DevicesFactoryHalInterface.h>
 #include <utils/Errors.h>
@@ -32,16 +35,26 @@
 class DevicesFactoryHalHidl : public DevicesFactoryHalInterface
 {
   public:
-    DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory);
+    explicit DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory);
+    void onFirstRef() override;
 
     // Opens a device with the specified name. To close the device, it is
     // necessary to release references to the returned object.
-    virtual status_t openDevice(const char *name, sp<DeviceHalInterface> *device);
+    status_t openDevice(const char *name, sp<DeviceHalInterface> *device) override;
 
-            status_t getHalPids(std::vector<pid_t> *pids) override;
+    status_t getHalPids(std::vector<pid_t> *pids) override;
+
+    status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
 
   private:
-    std::vector<sp<IDevicesFactory>> mDeviceFactories;
+    friend class ServiceNotificationListener;
+    void addDeviceFactory(sp<IDevicesFactory> factory, bool needToNotify);
+    std::vector<sp<IDevicesFactory>> copyDeviceFactories();
+
+    std::mutex mLock;
+    std::vector<sp<IDevicesFactory>> mDeviceFactories;  // GUARDED_BY(mLock)
+    wp<DevicesFactoryHalCallback> mCallback;  // GUARDED_BY(mLock)
+    bool mHaveUndeliveredNotifications = false;  // GUARDED_BY(mLock)
 
     virtual ~DevicesFactoryHalHidl() = default;
 };
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp b/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
index 52f150a..cde8d85 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
+++ b/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
@@ -44,6 +44,13 @@
     return INVALID_OPERATION;
 }
 
+status_t DevicesFactoryHalHybrid::setCallbackOnce(sp<DevicesFactoryHalCallback> callback) {
+    if (mHidlFactory) {
+        return mHidlFactory->setCallbackOnce(callback);
+    }
+    return INVALID_OPERATION;
+}
+
 } // namespace CPP_VERSION
 
 extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {
diff --git a/media/libaudiohal/impl/DevicesFactoryHalHybrid.h b/media/libaudiohal/impl/DevicesFactoryHalHybrid.h
index 2189b36..568a1fb 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalHybrid.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalHybrid.h
@@ -38,6 +38,8 @@
 
             status_t getHalPids(std::vector<pid_t> *pids) override;
 
+            status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;
+
   private:
     sp<DevicesFactoryHalInterface> mLocalFactory;
     sp<DevicesFactoryHalInterface> mHidlFactory;
diff --git a/media/libaudiohal/impl/DevicesFactoryHalLocal.h b/media/libaudiohal/impl/DevicesFactoryHalLocal.h
index 2b011f4..32bf362 100644
--- a/media/libaudiohal/impl/DevicesFactoryHalLocal.h
+++ b/media/libaudiohal/impl/DevicesFactoryHalLocal.h
@@ -37,6 +37,10 @@
                 return INVALID_OPERATION;
             }
 
+            status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback __unused) override {
+                return INVALID_OPERATION;
+            }
+
   private:
     friend class DevicesFactoryHalHybrid;
 
diff --git a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
index e9ac1ce..5091558 100644
--- a/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/DevicesFactoryHalInterface.h
@@ -24,6 +24,12 @@
 
 namespace android {
 
+class DevicesFactoryHalCallback : public RefBase
+{
+  public:
+    virtual void onNewDevicesAvailable() = 0;
+};
+
 class DevicesFactoryHalInterface : public RefBase
 {
   public:
@@ -33,6 +39,10 @@
 
     virtual status_t getHalPids(std::vector<pid_t> *pids) = 0;
 
+    // Sets a DevicesFactoryHalCallback to notify the client.
+    // The callback can be only set once.
+    virtual status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) = 0;
+
     static sp<DevicesFactoryHalInterface> create();
 
   protected:
diff --git a/media/libmedia/aidl/android/media/IResourceManagerService.aidl b/media/libmedia/aidl/android/media/IResourceManagerService.aidl
index 1b2d522..3dd0859 100644
--- a/media/libmedia/aidl/android/media/IResourceManagerService.aidl
+++ b/media/libmedia/aidl/android/media/IResourceManagerService.aidl
@@ -94,12 +94,4 @@
      *        remove existing override on originalPid if newPid is -1.
      */
     void overridePid(int originalPid, int newPid);
-
-    /**
-     * Mark a client for pending removal
-     *
-     * @param pid pid from which the client's resources will be removed.
-     * @param clientId clientId within the pid that will be removed.
-     */
-    void markClientForPendingRemoval(int pid, long clientId);
 }
diff --git a/media/libstagefright/FrameCaptureLayer.cpp b/media/libstagefright/FrameCaptureLayer.cpp
index 815057d..d2cfd41 100644
--- a/media/libstagefright/FrameCaptureLayer.cpp
+++ b/media/libstagefright/FrameCaptureLayer.cpp
@@ -67,7 +67,8 @@
 bool isHdrY410(const BufferItem &bi) {
     ui::Dataspace dataspace = translateDataspace(static_cast<ui::Dataspace>(bi.mDataSpace));
     // pixel format is HDR Y410 masquerading as RGBA_1010102
-    return (dataspace == ui::Dataspace::BT2020_ITU_PQ &&
+    return ((dataspace == ui::Dataspace::BT2020_ITU_PQ ||
+            dataspace == ui::Dataspace::BT2020_ITU_HLG) &&
             bi.mGraphicBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102);
 }
 
diff --git a/media/libstagefright/FrameDecoder.cpp b/media/libstagefright/FrameDecoder.cpp
index 3c4524b..734f5bb 100644
--- a/media/libstagefright/FrameDecoder.cpp
+++ b/media/libstagefright/FrameDecoder.cpp
@@ -248,7 +248,8 @@
         transfer = 0;
     }
     return standard == ColorUtils::kColorStandardBT2020 &&
-            transfer == ColorUtils::kColorTransferST2084;
+            (transfer == ColorUtils::kColorTransferST2084 ||
+            transfer == ColorUtils::kColorTransferHLG);
 }
 
 status_t FrameDecoder::init(
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 3e39c6d..b597583 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -199,7 +199,6 @@
     void addResource(const MediaResourceParcel &resource);
     void removeResource(const MediaResourceParcel &resource);
     void removeClient();
-    void markClientForPendingRemoval();
     bool reclaimResource(const std::vector<MediaResourceParcel> &resources);
 
 private:
@@ -281,14 +280,6 @@
     mService->removeClient(mPid, getId(mClient));
 }
 
-void MediaCodec::ResourceManagerServiceProxy::markClientForPendingRemoval() {
-    Mutex::Autolock _l(mLock);
-    if (mService == nullptr) {
-        return;
-    }
-    mService->markClientForPendingRemoval(mPid, getId(mClient));
-}
-
 bool MediaCodec::ResourceManagerServiceProxy::reclaimResource(
         const std::vector<MediaResourceParcel> &resources) {
     Mutex::Autolock _l(mLock);
@@ -1441,13 +1432,7 @@
 
 status_t MediaCodec::release() {
     sp<AMessage> msg = new AMessage(kWhatRelease, this);
-    sp<AMessage> response;
-    return PostAndAwaitResponse(msg, &response);
-}
 
-status_t MediaCodec::releaseAsync() {
-    sp<AMessage> msg = new AMessage(kWhatRelease, this);
-    msg->setInt32("async", 1);
     sp<AMessage> response;
     return PostAndAwaitResponse(msg, &response);
 }
@@ -2615,9 +2600,7 @@
 
                     mResourceManagerProxy->removeClient();
 
-                    if (mReplyID != nullptr) {
-                        (new AMessage)->postReply(mReplyID);
-                    }
+                    (new AMessage)->postReply(mReplyID);
                     break;
                 }
 
@@ -3016,14 +2999,6 @@
                 pushBlankBuffersToNativeWindow(mSurface.get());
             }
 
-            int32_t async = 0;
-            if (msg->findInt32("async", &async) && async) {
-                mResourceManagerProxy->markClientForPendingRemoval();
-                handleSetSurface(NULL);
-                (new AMessage)->postReply(mReplyID);
-                mReplyID = 0;
-            }
-
             break;
         }
 
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 9fe09fa..050d7c2 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -94,11 +94,16 @@
         return ERROR_UNSUPPORTED;
     }
 
+    status_t err = OK;
     if (!mCasToken.empty()) {
-        mImpl->setMediaCas(mCasToken);
+        err = mImpl->setMediaCas(mCasToken);
+        if (err != OK) {
+            ALOGE("%s: failed to setMediaCas (%d)", __FUNCTION__, err);
+            return err;
+        }
     }
 
-    status_t err = updateDurationAndBitrate();
+    err = updateDurationAndBitrate();
     if (err == OK) {
         mDataSource = dataSource;
     }
@@ -131,7 +136,11 @@
     }
 
     if (!mCasToken.empty()) {
-        mImpl->setMediaCas(mCasToken);
+        err = mImpl->setMediaCas(mCasToken);
+        if (err != OK) {
+            ALOGE("%s: failed to setMediaCas (%d)", __FUNCTION__, err);
+            return err;
+        }
     }
 
     err = updateDurationAndBitrate();
@@ -161,7 +170,11 @@
     }
 
     if (!mCasToken.empty()) {
-        mImpl->setMediaCas(mCasToken);
+        err = mImpl->setMediaCas(mCasToken);
+        if (err != OK) {
+            ALOGE("%s: failed to setMediaCas (%d)", __FUNCTION__, err);
+            return err;
+        }
     }
 
     err = updateDurationAndBitrate();
@@ -195,8 +208,12 @@
     mCasToken = casToken;
 
     if (mImpl != NULL) {
-        mImpl->setMediaCas(casToken);
-        status_t err = updateDurationAndBitrate();
+        status_t err = mImpl->setMediaCas(casToken);
+        if (err != OK) {
+            ALOGE("%s: failed to setMediaCas (%d)", __FUNCTION__, err);
+            return err;
+        }
+        err = updateDurationAndBitrate();
         if (err != OK) {
             return err;
         }
diff --git a/media/libstagefright/codecs/amrnb/common/Android.bp b/media/libstagefright/codecs/amrnb/common/Android.bp
index ea8b073..bcf63d5 100644
--- a/media/libstagefright/codecs/amrnb/common/Android.bp
+++ b/media/libstagefright/codecs/amrnb/common/Android.bp
@@ -1,6 +1,7 @@
 cc_library {
     name: "libstagefright_amrnb_common",
     vendor_available: true,
+    host_supported: true,
 
     srcs: [
         "src/add.cpp",
@@ -73,6 +74,12 @@
         "-Werror",
     ],
 
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+
     //addressing b/25409744
     //sanitize: {
     //    misc_undefined: [
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.bp b/media/libstagefright/codecs/amrnb/dec/Android.bp
index e18117e..3381d2e 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.bp
+++ b/media/libstagefright/codecs/amrnb/dec/Android.bp
@@ -1,6 +1,7 @@
 cc_library_static {
     name: "libstagefright_amrnbdec",
     vendor_available: true,
+    host_supported: true,
 
     srcs: [
         "src/a_refl.cpp",
@@ -61,6 +62,12 @@
         "libstagefright_amrnb_common",
         "liblog",
     ],
+
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
 
 //###############################################################################
@@ -100,6 +107,7 @@
 cc_test {
     name: "libstagefright_amrnbdec_test",
     gtest: false,
+    host_supported: true,
 
     srcs: ["test/amrnbdec_test.cpp"],
 
@@ -118,6 +126,12 @@
         "liblog",
     ],
 
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+
     //sanitize: {
     //    misc_undefined: [
     //        "signed-integer-overflow",
diff --git a/media/libstagefright/codecs/amrnb/fuzzer/Android.bp b/media/libstagefright/codecs/amrnb/fuzzer/Android.bp
new file mode 100644
index 0000000..54de1cc
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/fuzzer/Android.bp
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+
+cc_fuzz {
+    name: "amrnb_dec_fuzzer",
+    host_supported: true,
+    srcs: [
+        "amrnb_dec_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libstagefright_amrnbdec",
+        "libstagefright_amrnb_common",
+        "liblog",
+    ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+}
diff --git a/media/libstagefright/codecs/amrnb/fuzzer/README.md b/media/libstagefright/codecs/amrnb/fuzzer/README.md
new file mode 100644
index 0000000..7791b83
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/fuzzer/README.md
@@ -0,0 +1,62 @@
+# Fuzzer for libstagefright_amrnbdec decoder
+
+## Plugin Design Considerations
+The fuzzer plugin for AMR-NB is designed based on the understanding of the
+codec and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+AMR-NB supports the following parameters:
+1. Stream format (parameter name: `input_format`)
+2. 3GPP frame type (parameter name: `frame_type`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `input_format` | 0. `MIME_IETF` 1. `IF2` | Bit 0 (LSB) of 1st byte of data. |
+| `frame_type`   | 0. `AMR_475` 1. `AMR_515` 2. `AMR_59` 3. `AMR_67`  4. `AMR_74` 5. `AMR_795` 6. `AMR_102` 7. `AMR_122`  | Bits 3, 4 and 5 of 1st byte of data. |
+
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the codec using a loop.
+If the decode operation was successful, the input is advanced by the frame size
+which is based on `input_format` and `frame_type` selected.
+If the decode operation was un-successful, the input is still advanced by frame size so
+that the fuzzer can proceed to feed the next frame.
+
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build amrnb_dec_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) amrnb_dec_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some amrnb files to that folder
+Push this directory to device.
+
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/amrnb_dec_fuzzer/amrnb_dec_fuzzer CORPUS_DIR
+```
+To run on host
+```
+  $ $ANDROID_HOST_OUT/fuzz/x86_64/amrnb_dec_fuzzer/amrnb_dec_fuzzer CORPUS_DIR
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/media/libstagefright/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp b/media/libstagefright/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
new file mode 100644
index 0000000..d4e7e5c
--- /dev/null
+++ b/media/libstagefright/codecs/amrnb/fuzzer/amrnb_dec_fuzzer.cpp
@@ -0,0 +1,94 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *****************************************************************************
+ * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
+ */
+#include <string.h>
+#include <algorithm>
+#include "gsmamr_dec.h"
+
+// Constants for AMR-NB
+constexpr int32_t kSamplesPerFrame = L_FRAME;
+constexpr int32_t kBitsPerSample = 16;
+constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
+const bitstream_format kBitStreamFormats[2] = {MIME_IETF, IF2};
+const int32_t kLocalWmfDecBytesPerFrame[8] = {12, 13, 15, 17, 19, 20, 26, 31};
+const int32_t kLocalIf2DecBytesPerFrame[8] = {13, 14, 16, 18, 19, 21, 26, 31};
+
+class Codec {
+ public:
+  Codec() = default;
+  ~Codec() { deInitDecoder(); }
+  int16_t initDecoder();
+  void deInitDecoder();
+  void decodeFrames(const uint8_t *data, size_t size);
+
+ private:
+  void *mAmrHandle = nullptr;
+};
+
+int16_t Codec::initDecoder() { return GSMInitDecode(&mAmrHandle, (Word8 *)"AMRNBDecoder"); }
+
+void Codec::deInitDecoder() { GSMDecodeFrameExit(&mAmrHandle); }
+
+void Codec::decodeFrames(const uint8_t *data, size_t size) {
+  while (size > 0) {
+    uint8_t mode = *data;
+    bool bit = mode & 0x01;
+    bitstream_format bitsreamFormat = kBitStreamFormats[bit];
+    int32_t frameSize = 0;
+    /* Find frame type */
+    Frame_Type_3GPP frameType = static_cast<Frame_Type_3GPP>((mode >> 3) & 0x07);
+    ++data;
+    --size;
+    if (bit) {
+      frameSize = kLocalIf2DecBytesPerFrame[frameType];
+    } else {
+      frameSize = kLocalWmfDecBytesPerFrame[frameType];
+    }
+    int16_t outputBuf[kOutputBufferSize];
+    uint8_t *inputBuf = new uint8_t[frameSize];
+    if (!inputBuf) {
+      return;
+    }
+    int32_t minSize = std::min((int32_t)size, frameSize);
+    memcpy(inputBuf, data, minSize);
+    AMRDecode(mAmrHandle, frameType, inputBuf, outputBuf, bitsreamFormat);
+    /* AMRDecode() decodes minSize number of bytes if decode is successful.
+     * AMRDecode() returns -1 if decode fails.
+     * Even if no bytes are decoded, increment by minSize to ensure fuzzer proceeds
+     * to feed next data */
+    data += minSize;
+    size -= minSize;
+    delete[] inputBuf;
+  }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+  if (size < 2) {
+    return 0;
+  }
+  Codec *codec = new Codec();
+  if (!codec) {
+    return 0;
+  }
+  if (codec->initDecoder() == 0) {
+    codec->decodeFrames(data, size);
+  }
+  delete codec;
+  return 0;
+}
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 0e983b2..022c48e 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -139,8 +139,6 @@
     // object.
     status_t release();
 
-    status_t releaseAsync();
-
     status_t flush();
 
     status_t queueInputBuffer(
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 4adbad2..74a09d1 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -29,6 +29,7 @@
 #include <string>
 #include <sys/time.h>
 #include <sys/resource.h>
+#include <thread>
 
 #include <android/os/IExternalVibratorService.h>
 #include <binder/IPCThreadState.h>
@@ -144,6 +145,19 @@
     return sExternalVibratorService;
 }
 
+class DevicesFactoryHalCallbackImpl : public DevicesFactoryHalCallback {
+  public:
+    void onNewDevicesAvailable() override {
+        // Start a detached thread to execute notification in parallel.
+        // This is done to prevent mutual blocking of audio_flinger and
+        // audio_policy services during system initialization.
+        std::thread notifier([]() {
+            AudioSystem::onNewAudioModulesAvailable();
+        });
+        notifier.detach();
+    }
+};
+
 // ----------------------------------------------------------------------------
 
 std::string formatToString(audio_format_t format) {
@@ -227,6 +241,9 @@
     mMode = AUDIO_MODE_NORMAL;
 
     gAudioFlinger = this;
+
+    mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
+    mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
 }
 
 status_t AudioFlinger::setAudioHalPids(const std::vector<pid_t>& pids) {
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index d69b49d..6d7bf3c 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -105,6 +105,7 @@
 class AudioBuffer;
 class AudioResampler;
 class DeviceHalInterface;
+class DevicesFactoryHalCallback;
 class DevicesFactoryHalInterface;
 class EffectsFactoryHalInterface;
 class FastMixer;
@@ -837,6 +838,7 @@
                 DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>  mAudioHwDevs;
 
                 sp<DevicesFactoryHalInterface> mDevicesFactoryHal;
+                sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback;
 
     // for dump, indicates which hardware operation is currently in progress (but not stream ops)
     enum hardware_call_state {
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 2f3724f..82b9c96 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1395,7 +1395,11 @@
 
 void AudioFlinger::EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
 {
-    if (mEffectCallback->isOffloadOrDirect() && !isNonOffloadableEnabled_l()) {
+    // for offload or direct thread, if the effect chain has non-offloadable
+    // effect and any effect module within the chain has volume control, then
+    // volume control is delegated to effect, otherwise, set volume to hal.
+    if (mEffectCallback->isOffloadOrDirect() &&
+        !(isNonOffloadableEnabled_l() && hasVolumeControlEnabled_l())) {
         float vol_l = (float)left / (1 << 24);
         float vol_r = (float)right / (1 << 24);
         mEffectCallback->setVolumeForOutput(vol_l, vol_r);
@@ -2296,6 +2300,13 @@
     }
 }
 
+bool AudioFlinger::EffectChain::hasVolumeControlEnabled_l() const {
+    for (const auto &effect : mEffects) {
+        if (effect->isVolumeControlEnabled()) return true;
+    }
+    return false;
+}
+
 // setVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
 bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
 {
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 4901451..2826297 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -596,6 +596,9 @@
 
     void setThread(const sp<ThreadBase>& thread);
 
+    // true if any effect module within the chain has volume control
+    bool hasVolumeControlEnabled_l() const;
+
     void setVolumeForOutput_l(uint32_t left, uint32_t right);
 
     mutable  Mutex mLock;        // mutex protecting effect list
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 4d53be4..8d0e5db 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -83,6 +83,10 @@
     // configuration functions
     //
 
+    // Informs APM that new HAL modules are available. This typically happens
+    // due to registration of an audio HAL service.
+    virtual void onNewAudioModulesAvailable() = 0;
+
     // indicate a change in device connection status
     virtual status_t setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
index e59386f..395bc70 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyConfig.h
@@ -37,13 +37,13 @@
 {
 public:
     AudioPolicyConfig(HwModuleCollection &hwModules,
-                      DeviceVector &availableOutputDevices,
-                      DeviceVector &availableInputDevices,
+                      DeviceVector &outputDevices,
+                      DeviceVector &inputDevices,
                       sp<DeviceDescriptor> &defaultOutputDevice)
         : mEngineLibraryNameSuffix(kDefaultEngineLibraryNameSuffix),
           mHwModules(hwModules),
-          mAvailableOutputDevices(availableOutputDevices),
-          mAvailableInputDevices(availableInputDevices),
+          mOutputDevices(outputDevices),
+          mInputDevices(inputDevices),
           mDefaultOutputDevice(defaultOutputDevice),
           mIsSpeakerDrcEnabled(false),
           mIsCallScreenModeSupported(false)
@@ -70,23 +70,23 @@
         mHwModules = hwModules;
     }
 
-    void addAvailableDevice(const sp<DeviceDescriptor> &availableDevice)
+    void addDevice(const sp<DeviceDescriptor> &device)
     {
-        if (audio_is_output_device(availableDevice->type())) {
-            mAvailableOutputDevices.add(availableDevice);
-        } else if (audio_is_input_device(availableDevice->type())) {
-            mAvailableInputDevices.add(availableDevice);
+        if (audio_is_output_device(device->type())) {
+            mOutputDevices.add(device);
+        } else if (audio_is_input_device(device->type())) {
+            mInputDevices.add(device);
         }
     }
 
-    void addAvailableInputDevices(const DeviceVector &availableInputDevices)
+    void addInputDevices(const DeviceVector &inputDevices)
     {
-        mAvailableInputDevices.add(availableInputDevices);
+        mInputDevices.add(inputDevices);
     }
 
-    void addAvailableOutputDevices(const DeviceVector &availableOutputDevices)
+    void addOutputDevices(const DeviceVector &outputDevices)
     {
-        mAvailableOutputDevices.add(availableOutputDevices);
+        mOutputDevices.add(outputDevices);
     }
 
     bool isSpeakerDrcEnabled() const { return mIsSpeakerDrcEnabled; }
@@ -106,14 +106,14 @@
 
     const HwModuleCollection getHwModules() const { return mHwModules; }
 
-    const DeviceVector &getAvailableInputDevices() const
+    const DeviceVector &getInputDevices() const
     {
-        return mAvailableInputDevices;
+        return mInputDevices;
     }
 
-    const DeviceVector &getAvailableOutputDevices() const
+    const DeviceVector &getOutputDevices() const
     {
-        return mAvailableOutputDevices;
+        return mOutputDevices;
     }
 
     void setDefaultOutputDevice(const sp<DeviceDescriptor> &defaultDevice)
@@ -134,13 +134,11 @@
         sp<AudioProfile> micProfile = new AudioProfile(
                 AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000);
         defaultInputDevice->addAudioProfile(micProfile);
-        mAvailableOutputDevices.add(mDefaultOutputDevice);
-        mAvailableInputDevices.add(defaultInputDevice);
+        mOutputDevices.add(mDefaultOutputDevice);
+        mInputDevices.add(defaultInputDevice);
 
         sp<HwModule> module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY, 2 /*halVersionMajor*/);
         mHwModules.add(module);
-        mDefaultOutputDevice->attach(module);
-        defaultInputDevice->attach(module);
 
         sp<OutputProfile> outProfile = new OutputProfile("primary");
         outProfile->addAudioProfile(
@@ -191,8 +189,8 @@
     std::string mSource;
     std::string mEngineLibraryNameSuffix;
     HwModuleCollection &mHwModules; /**< Collection of Module, with Profiles, i.e. Mix Ports. */
-    DeviceVector &mAvailableOutputDevices;
-    DeviceVector &mAvailableInputDevices;
+    DeviceVector &mOutputDevices;
+    DeviceVector &mInputDevices;
     sp<DeviceDescriptor> &mDefaultOutputDevice;
     // TODO: remove when legacy conf file is removed. true on devices that use DRC on the
     // DEVICE_CATEGORY_SPEAKER path to boost soft sounds, used to adjust volume curves accordingly.
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
index 1b2f7c7..883e713 100644
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
@@ -653,7 +653,7 @@
                         sp<DeviceDescriptor> device = module->getDeclaredDevices().
                                 getDeviceFromTagName(std::string(reinterpret_cast<const char*>(
                                                         attachedDevice.get())));
-                        ctx->addAvailableDevice(device);
+                        ctx->addDevice(device);
                     }
                 }
             }
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 0aa087a..5a012bf 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -4397,7 +4397,7 @@
     mpClientInterface(clientInterface),
     mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
     mA2dpSuspended(false),
-    mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices, mDefaultOutputDevice),
+    mConfig(mHwModulesAll, mOutputDevicesAll, mInputDevicesAll, mDefaultOutputDevice),
     mAudioPortGeneration(1),
     mBeaconMuteRefCount(0),
     mBeaconPlayingRefCount(0),
@@ -4442,141 +4442,9 @@
         return status;
     }
 
-    // mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
+    // after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;
     // open all output streams needed to access attached devices
-    for (const auto& hwModule : mHwModulesAll) {
-        hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
-        if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
-            ALOGW("could not open HW module %s", hwModule->getName());
-            continue;
-        }
-        mHwModules.push_back(hwModule);
-        // open all output streams needed to access attached devices
-        // except for direct output streams that are only opened when they are actually
-        // required by an app.
-        // This also validates mAvailableOutputDevices list
-        for (const auto& outProfile : hwModule->getOutputProfiles()) {
-            if (!outProfile->canOpenNewIo()) {
-                ALOGE("Invalid Output profile max open count %u for profile %s",
-                      outProfile->maxOpenCount, outProfile->getTagName().c_str());
-                continue;
-            }
-            if (!outProfile->hasSupportedDevices()) {
-                ALOGW("Output profile contains no device on module %s", hwModule->getName());
-                continue;
-            }
-            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0) {
-                mTtsOutputAvailable = true;
-            }
-
-            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
-                continue;
-            }
-            const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
-            DeviceVector availProfileDevices = supportedDevices.filter(mAvailableOutputDevices);
-            sp<DeviceDescriptor> supportedDevice = 0;
-            if (supportedDevices.contains(mDefaultOutputDevice)) {
-                supportedDevice = mDefaultOutputDevice;
-            } else {
-                // choose first device present in profile's SupportedDevices also part of
-                // mAvailableOutputDevices.
-                if (availProfileDevices.isEmpty()) {
-                    continue;
-                }
-                supportedDevice = availProfileDevices.itemAt(0);
-            }
-            if (!mAvailableOutputDevices.contains(supportedDevice)) {
-                continue;
-            }
-            sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
-                                                                                 mpClientInterface);
-            audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
-            status_t status = outputDesc->open(nullptr, DeviceVector(supportedDevice),
-                                               AUDIO_STREAM_DEFAULT,
-                                               AUDIO_OUTPUT_FLAG_NONE, &output);
-            if (status != NO_ERROR) {
-                ALOGW("Cannot open output stream for devices %s on hw module %s",
-                      supportedDevice->toString().c_str(), hwModule->getName());
-                continue;
-            }
-            for (const auto &device : availProfileDevices) {
-                // give a valid ID to an attached device once confirmed it is reachable
-                if (!device->isAttached()) {
-                    device->attach(hwModule);
-                }
-            }
-            if (mPrimaryOutput == 0 &&
-                    outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
-                mPrimaryOutput = outputDesc;
-            }
-            addOutput(output, outputDesc);
-            setOutputDevices(outputDesc,
-                             DeviceVector(supportedDevice),
-                             true,
-                             0,
-                             NULL);
-        }
-        // open input streams needed to access attached devices to validate
-        // mAvailableInputDevices list
-        for (const auto& inProfile : hwModule->getInputProfiles()) {
-            if (!inProfile->canOpenNewIo()) {
-                ALOGE("Invalid Input profile max open count %u for profile %s",
-                      inProfile->maxOpenCount, inProfile->getTagName().c_str());
-                continue;
-            }
-            if (!inProfile->hasSupportedDevices()) {
-                ALOGW("Input profile contains no device on module %s", hwModule->getName());
-                continue;
-            }
-            // chose first device present in profile's SupportedDevices also part of
-            // available input devices
-            const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
-            DeviceVector availProfileDevices = supportedDevices.filter(mAvailableInputDevices);
-            if (availProfileDevices.isEmpty()) {
-                ALOGE("%s: Input device list is empty!", __FUNCTION__);
-                continue;
-            }
-            sp<AudioInputDescriptor> inputDesc =
-                    new AudioInputDescriptor(inProfile, mpClientInterface);
-
-            audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
-            status_t status = inputDesc->open(nullptr,
-                                              availProfileDevices.itemAt(0),
-                                              AUDIO_SOURCE_MIC,
-                                              AUDIO_INPUT_FLAG_NONE,
-                                              &input);
-            if (status != NO_ERROR) {
-                ALOGW("Cannot open input stream for device %s on hw module %s",
-                      availProfileDevices.toString().c_str(),
-                      hwModule->getName());
-                continue;
-            }
-            for (const auto &device : availProfileDevices) {
-                // give a valid ID to an attached device once confirmed it is reachable
-                if (!device->isAttached()) {
-                    device->attach(hwModule);
-                    device->importAudioPortAndPickAudioProfile(inProfile, true);
-                }
-            }
-            inputDesc->close();
-        }
-    }
-    // make sure all attached devices have been allocated a unique ID
-    auto checkAndSetAvailable = [this](auto& devices) {
-        for (size_t i = 0; i < devices.size();) {
-            const auto &device = devices[i];
-            if (!device->isAttached()) {
-                ALOGW("device %s is unreachable", device->toString().c_str());
-                devices.remove(device);
-                continue;
-            }
-            // Device is now validated and can be appended to the available devices of the engine
-            setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
-            i++;
-        }
-    };
-    checkAndSetAvailable(mAvailableOutputDevices);
-    checkAndSetAvailable(mAvailableInputDevices);
+    onNewAudioModulesAvailable();
 
     // make sure default device is reachable
     if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
@@ -4631,6 +4499,134 @@
 
 // ---
 
+void AudioPolicyManager::onNewAudioModulesAvailable()
+{
+    for (const auto& hwModule : mHwModulesAll) {
+        if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
+            continue;
+        }
+        hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
+        if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
+            ALOGW("could not open HW module %s", hwModule->getName());
+            continue;
+        }
+        mHwModules.push_back(hwModule);
+        // open all output streams needed to access attached devices
+        // except for direct output streams that are only opened when they are actually
+        // required by an app.
+        // This also validates mAvailableOutputDevices list
+        for (const auto& outProfile : hwModule->getOutputProfiles()) {
+            if (!outProfile->canOpenNewIo()) {
+                ALOGE("Invalid Output profile max open count %u for profile %s",
+                      outProfile->maxOpenCount, outProfile->getTagName().c_str());
+                continue;
+            }
+            if (!outProfile->hasSupportedDevices()) {
+                ALOGW("Output profile contains no device on module %s", hwModule->getName());
+                continue;
+            }
+            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0) {
+                mTtsOutputAvailable = true;
+            }
+
+            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
+                continue;
+            }
+            const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
+            DeviceVector availProfileDevices = supportedDevices.filter(mOutputDevicesAll);
+            sp<DeviceDescriptor> supportedDevice = 0;
+            if (supportedDevices.contains(mDefaultOutputDevice)) {
+                supportedDevice = mDefaultOutputDevice;
+            } else {
+                // choose first device present in profile's SupportedDevices also part of
+                // mAvailableOutputDevices.
+                if (availProfileDevices.isEmpty()) {
+                    continue;
+                }
+                supportedDevice = availProfileDevices.itemAt(0);
+            }
+            if (!mOutputDevicesAll.contains(supportedDevice)) {
+                continue;
+            }
+            sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
+                                                                                 mpClientInterface);
+            audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+            status_t status = outputDesc->open(nullptr, DeviceVector(supportedDevice),
+                                               AUDIO_STREAM_DEFAULT,
+                                               AUDIO_OUTPUT_FLAG_NONE, &output);
+            if (status != NO_ERROR) {
+                ALOGW("Cannot open output stream for devices %s on hw module %s",
+                      supportedDevice->toString().c_str(), hwModule->getName());
+                continue;
+            }
+            for (const auto &device : availProfileDevices) {
+                // give a valid ID to an attached device once confirmed it is reachable
+                if (!device->isAttached()) {
+                    device->attach(hwModule);
+                    mAvailableOutputDevices.add(device);
+                    setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
+                }
+            }
+            if (mPrimaryOutput == 0 &&
+                    outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
+                mPrimaryOutput = outputDesc;
+            }
+            addOutput(output, outputDesc);
+            setOutputDevices(outputDesc,
+                             DeviceVector(supportedDevice),
+                             true,
+                             0,
+                             NULL);
+        }
+        // open input streams needed to access attached devices to validate
+        // mAvailableInputDevices list
+        for (const auto& inProfile : hwModule->getInputProfiles()) {
+            if (!inProfile->canOpenNewIo()) {
+                ALOGE("Invalid Input profile max open count %u for profile %s",
+                      inProfile->maxOpenCount, inProfile->getTagName().c_str());
+                continue;
+            }
+            if (!inProfile->hasSupportedDevices()) {
+                ALOGW("Input profile contains no device on module %s", hwModule->getName());
+                continue;
+            }
+            // chose first device present in profile's SupportedDevices also part of
+            // available input devices
+            const DeviceVector &supportedDevices = inProfile->getSupportedDevices();
+            DeviceVector availProfileDevices = supportedDevices.filter(mInputDevicesAll);
+            if (availProfileDevices.isEmpty()) {
+                ALOGE("%s: Input device list is empty!", __FUNCTION__);
+                continue;
+            }
+            sp<AudioInputDescriptor> inputDesc =
+                    new AudioInputDescriptor(inProfile, mpClientInterface);
+
+            audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
+            status_t status = inputDesc->open(nullptr,
+                                              availProfileDevices.itemAt(0),
+                                              AUDIO_SOURCE_MIC,
+                                              AUDIO_INPUT_FLAG_NONE,
+                                              &input);
+            if (status != NO_ERROR) {
+                ALOGW("Cannot open input stream for device %s on hw module %s",
+                      availProfileDevices.toString().c_str(),
+                      hwModule->getName());
+                continue;
+            }
+            for (const auto &device : availProfileDevices) {
+                // give a valid ID to an attached device once confirmed it is reachable
+                if (!device->isAttached()) {
+                    device->attach(hwModule);
+                    device->importAudioPortAndPickAudioProfile(inProfile, true);
+                    mAvailableInputDevices.add(device);
+                    setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
+                }
+            }
+            inputDesc->close();
+        }
+    }
+}
+
 void AudioPolicyManager::addOutput(audio_io_handle_t output,
                                    const sp<SwAudioOutputDescriptor>& outputDesc)
 {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index b0adbc7..8121f86 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -325,6 +325,8 @@
 
         bool isCallScreenModeSupported() override;
 
+        void onNewAudioModulesAvailable() override;
+
         status_t initialize();
 
 protected:
@@ -729,6 +731,8 @@
         SwAudioOutputCollection mPreviousOutputs;
         AudioInputCollection mInputs;     // list of input descriptors
 
+        DeviceVector  mOutputDevicesAll; // all output devices from the config
+        DeviceVector  mInputDevicesAll;  // all input devices from the config
         DeviceVector  mAvailableOutputDevices; // all available output devices
         DeviceVector  mAvailableInputDevices;  // all available input devices
 
@@ -739,9 +743,8 @@
 
         EffectDescriptorCollection mEffects;  // list of registered audio effects
         sp<DeviceDescriptor> mDefaultOutputDevice; // output device selected by default at boot time
-        HwModuleCollection mHwModules; // contains only modules that have been loaded successfully
-        HwModuleCollection mHwModulesAll; // normally not needed, used during construction and for
-                                          // dumps
+        HwModuleCollection mHwModules; // contains modules that have been loaded successfully
+        HwModuleCollection mHwModulesAll; // contains all modules declared in the config
 
         AudioPolicyConfig mConfig;
 
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 38801ec..0da3b9c 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -66,6 +66,14 @@
 
 // ----------------------------------------------------------------------------
 
+void AudioPolicyService::doOnNewAudioModulesAvailable()
+{
+    if (mAudioPolicyManager == NULL) return;
+    Mutex::Autolock _l(mLock);
+    AutoCallerClear acc;
+    mAudioPolicyManager->onNewAudioModulesAvailable();
+}
+
 status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
                                                   audio_policy_dev_state_t state,
                                                   const char *device_address,
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 1b8c202..bf38477 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1321,6 +1321,16 @@
                         mLock.lock();
                     }
                     } break;
+                case AUDIO_MODULES_UPDATE: {
+                    ALOGV("AudioCommandThread() processing audio modules update");
+                    svc = mService.promote();
+                    if (svc == 0) {
+                        break;
+                    }
+                    mLock.unlock();
+                    svc->doOnNewAudioModulesAvailable();
+                    mLock.lock();
+                    } break;
 
                 default:
                     ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
@@ -1610,6 +1620,13 @@
     sendCommand(command);
 }
 
+void AudioPolicyService::AudioCommandThread::audioModulesUpdateCommand()
+{
+    sp<AudioCommand> command = new AudioCommand();
+    command->mCommand = AUDIO_MODULES_UPDATE;
+    sendCommand(command);
+}
+
 status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
 {
     {
@@ -1857,6 +1874,11 @@
     mAudioCommandThread->setEffectSuspendedCommand(effectId, sessionId, suspended);
 }
 
+void AudioPolicyService::onNewAudioModulesAvailable()
+{
+    mAudioCommandThread->audioModulesUpdateCommand();
+}
+
 
 extern "C" {
 audio_module_handle_t aps_load_hw_module(void *service __unused,
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index c3c87f1..ff99124 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -60,6 +60,7 @@
     // BnAudioPolicyService (see AudioPolicyInterface for method descriptions)
     //
 
+    void onNewAudioModulesAvailable() override;
     virtual status_t setDeviceConnectionState(audio_devices_t device,
                                               audio_policy_dev_state_t state,
                                               const char *device_address,
@@ -277,6 +278,7 @@
 
             bool isCallScreenModeSupported() override;
 
+            void doOnNewAudioModulesAvailable();
             status_t doStopOutput(audio_port_handle_t portId);
             void doReleaseOutput(audio_port_handle_t portId);
 
@@ -463,6 +465,7 @@
             DYN_POLICY_MIX_STATE_UPDATE,
             RECORDING_CONFIGURATION_UPDATE,
             SET_EFFECT_SUSPENDED,
+            AUDIO_MODULES_UPDATE,
         };
 
         AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -508,6 +511,7 @@
                     void        setEffectSuspendedCommand(int effectId,
                                                           audio_session_t sessionId,
                                                           bool suspended);
+                    void        audioModulesUpdateCommand();
                     void        insertCommand_l(AudioCommand *command, int delayMs = 0);
     private:
         class AudioCommandData;
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index c2a92d7..af69466 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -15,6 +15,7 @@
  */
 
 #include <map>
+#include <set>
 
 #include <system/audio.h>
 #include <utils/Log.h>
@@ -27,7 +28,10 @@
 class AudioPolicyManagerTestClient : public AudioPolicyTestClient {
 public:
     // AudioPolicyClientInterface implementation
-    audio_module_handle_t loadHwModule(const char * /*name*/) override {
+    audio_module_handle_t loadHwModule(const char* name) override {
+        if (!mAllowedModuleNames.empty() && !mAllowedModuleNames.count(name)) {
+            return AUDIO_MODULE_HANDLE_NONE;
+        }
         return mNextModuleHandle++;
     }
 
@@ -101,11 +105,18 @@
         return &it->second;
     };
 
+    audio_module_handle_t peekNextModuleHandle() const { return mNextModuleHandle; }
+
+    void swapAllowedModuleNames(std::set<std::string>&& names = {}) {
+        mAllowedModuleNames.swap(names);
+    }
+
 private:
     audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
     audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
     audio_patch_handle_t mNextPatchHandle = AUDIO_PATCH_HANDLE_NONE + 1;
     std::map<audio_patch_handle_t, struct audio_patch> mActivePatches;
+    std::set<std::string> mAllowedModuleNames;
 };
 
 } // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index bafcc63..922a538 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -27,6 +27,8 @@
     using AudioPolicyManager::loadConfig;
     using AudioPolicyManager::initialize;
     using AudioPolicyManager::getOutputs;
+    using AudioPolicyManager::getAvailableOutputDevices;
+    using AudioPolicyManager::getAvailableInputDevices;
 };
 
 }  // namespace android
diff --git a/services/audiopolicy/tests/audio_health_tests.cpp b/services/audiopolicy/tests/audio_health_tests.cpp
index 8736cf1..b5c67a1 100644
--- a/services/audiopolicy/tests/audio_health_tests.cpp
+++ b/services/audiopolicy/tests/audio_health_tests.cpp
@@ -67,10 +67,10 @@
     manager.loadConfig();
     ASSERT_NE("AudioPolicyConfig::setDefault", manager.getConfig().getSource());
 
-    for (auto desc : manager.getConfig().getAvailableInputDevices()) {
+    for (auto desc : manager.getConfig().getInputDevices()) {
         ASSERT_NE(attachedDevices.end(), attachedDevices.find(desc->type()));
     }
-    for (auto desc : manager.getConfig().getAvailableOutputDevices()) {
+    for (auto desc : manager.getConfig().getOutputDevices()) {
         ASSERT_NE(attachedDevices.end(), attachedDevices.find(desc->type()));
     }
 }
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 2a8349c..7d92f34 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -298,9 +298,9 @@
     audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
     uid_t uid = 42;
     const PatchCountCheck patchCount = snapshotPatchCount();
-    ASSERT_FALSE(mManager->getConfig().getAvailableInputDevices().isEmpty());
+    ASSERT_FALSE(mManager->getAvailableInputDevices().isEmpty());
     PatchBuilder patchBuilder;
-    patchBuilder.addSource(mManager->getConfig().getAvailableInputDevices()[0]).
+    patchBuilder.addSource(mManager->getAvailableInputDevices()[0]).
             addSink(mManager->getConfig().getDefaultOutputDevice());
     ASSERT_EQ(NO_ERROR, mManager->createAudioPatch(patchBuilder.patch(), &handle, uid));
     ASSERT_NE(AUDIO_PATCH_HANDLE_NONE, handle);
@@ -334,15 +334,13 @@
     sp<AudioProfile> pcmInputProfile = new AudioProfile(
             AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 44100);
     mMsdInputDevice->addAudioProfile(pcmInputProfile);
-    config.addAvailableDevice(mMsdOutputDevice);
-    config.addAvailableDevice(mMsdInputDevice);
+    config.addDevice(mMsdOutputDevice);
+    config.addDevice(mMsdInputDevice);
 
     sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
     HwModuleCollection modules = config.getHwModules();
     modules.add(msdModule);
     config.setHwModules(modules);
-    mMsdOutputDevice->attach(msdModule);
-    mMsdInputDevice->attach(msdModule);
 
     sp<OutputProfile> msdOutputProfile = new OutputProfile("msd input");
     msdOutputProfile->addAudioProfile(pcmOutputProfile);
@@ -1127,3 +1125,40 @@
                     AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ),
             "low latency");
 }
+
+class AudioPolicyManagerDynamicHwModulesTest : public AudioPolicyManagerTestWithConfigurationFile {
+protected:
+    void SetUpManagerConfig() override;
+};
+
+void AudioPolicyManagerDynamicHwModulesTest::SetUpManagerConfig() {
+    AudioPolicyManagerTestWithConfigurationFile::SetUpManagerConfig();
+    // Only allow successful opening of "primary" hw module during APM initialization.
+    mClient->swapAllowedModuleNames({"primary"});
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, InitSuccess) {
+    // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, DynamicAddition) {
+    const auto handleBefore = mClient->peekNextModuleHandle();
+    mManager->onNewAudioModulesAvailable();
+    ASSERT_EQ(handleBefore, mClient->peekNextModuleHandle());
+    // Reset module loading restrictions.
+    mClient->swapAllowedModuleNames();
+    mManager->onNewAudioModulesAvailable();
+    const auto handleAfter = mClient->peekNextModuleHandle();
+    ASSERT_GT(handleAfter, handleBefore);
+    mManager->onNewAudioModulesAvailable();
+    ASSERT_EQ(handleAfter, mClient->peekNextModuleHandle());
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, AddedDeviceAvailable) {
+    ASSERT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, mManager->getDeviceConnectionState(
+                    AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0"));
+    mClient->swapAllowedModuleNames({"primary", "r_submix"});
+    mManager->onNewAudioModulesAvailable();
+    ASSERT_EQ(AUDIO_POLICY_DEVICE_STATE_AVAILABLE, mManager->getDeviceConnectionState(
+                    AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0"));
+}
diff --git a/services/mediametrics/MediaMetricsService.cpp b/services/mediametrics/MediaMetricsService.cpp
index d27fa5e..a6fefd2 100644
--- a/services/mediametrics/MediaMetricsService.cpp
+++ b/services/mediametrics/MediaMetricsService.cpp
@@ -386,7 +386,7 @@
                 break;
             }
             if (now > when && (now - when) <= mMaxRecordAgeNs) {
-                break;  // TODO: if we use BOOTTIME, should be monotonic.
+                break; // Note SYSTEM_TIME_REALTIME may not be monotonic.
             }
             if (i >= mMaxRecordsExpiredAtOnce) {
                 // this represents "one too many"; tell caller there are
diff --git a/services/mediametrics/TimeMachine.h b/services/mediametrics/TimeMachine.h
index f0bb2fb..a4c3693 100644
--- a/services/mediametrics/TimeMachine.h
+++ b/services/mediametrics/TimeMachine.h
@@ -93,7 +93,7 @@
 
         template <typename T>
         status_t getValue(const std::string &property, T* value, int64_t time = 0) const {
-            if (time == 0) time = systemTime(SYSTEM_TIME_BOOTTIME);
+            if (time == 0) time = systemTime(SYSTEM_TIME_REALTIME);
             const auto tsptr = mPropertyMap.find(property);
             if (tsptr == mPropertyMap.end()) return BAD_VALUE;
             const auto& timeSequence = tsptr->second;
@@ -122,7 +122,7 @@
         template <typename T>
         void putValue(const std::string &property,
                 T&& e, int64_t time = 0) {
-            if (time == 0) time = systemTime(SYSTEM_TIME_BOOTTIME);
+            if (time == 0) time = systemTime(SYSTEM_TIME_REALTIME);
             mLastModificationTime = time;
             if (mPropertyMap.size() >= kKeyMaxProperties &&
                     !mPropertyMap.count(property)) {
@@ -340,7 +340,7 @@
     /**
      * Individual property put.
      *
-     * Put takes in a time (if none is provided then BOOTTIME is used).
+     * Put takes in a time (if none is provided then SYSTEM_TIME_REALTIME is used).
      */
     template <typename T>
     status_t put(const std::string &url, T &&e, int64_t time = 0) {
@@ -349,7 +349,7 @@
         std::shared_ptr<KeyHistory> keyHistory =
             getKeyHistoryFromUrl(url, &key, &prop);
         if (keyHistory == nullptr) return BAD_VALUE;
-        if (time == 0) time = systemTime(SYSTEM_TIME_BOOTTIME);
+        if (time == 0) time = systemTime(SYSTEM_TIME_REALTIME);
         std::lock_guard lock(getLockForKey(key));
         keyHistory->putValue(prop, std::forward<T>(e), time);
         return NO_ERROR;
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index ff45c87..be5af00 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -114,7 +114,6 @@
         info.uid = uid;
         info.clientId = clientId;
         info.client = client;
-        info.pendingRemoval = false;
 
         index = infos.add(clientId, info);
     }
@@ -649,36 +648,6 @@
     return Status::ok();
 }
 
-Status ResourceManagerService::markClientForPendingRemoval(int32_t pid, int64_t clientId) {
-    String8 log = String8::format(
-            "markClientForPendingRemoval(pid %d, clientId %lld)",
-            pid, (long long) clientId);
-    mServiceLog->add(log);
-
-    Mutex::Autolock lock(mLock);
-    if (!mProcessInfo->isValidPid(pid)) {
-        ALOGE("Rejected markClientForPendingRemoval call with invalid pid.");
-        return Status::fromServiceSpecificError(BAD_VALUE);
-    }
-    ssize_t index = mMap.indexOfKey(pid);
-    if (index < 0) {
-        ALOGV("markClientForPendingRemoval: didn't find pid %d for clientId %lld",
-              pid, (long long)clientId);
-        return Status::ok();
-    }
-    ResourceInfos &infos = mMap.editValueAt(index);
-
-    index = infos.indexOfKey(clientId);
-    if (index < 0) {
-        ALOGV("markClientForPendingRemoval: didn't find clientId %lld", (long long) clientId);
-        return Status::ok();
-    }
-
-    ResourceInfo &info = infos.editValueAt(index);
-    info.pendingRemoval = true;
-    return Status::ok();
-}
-
 bool ResourceManagerService::getPriority_l(int pid, int* priority) {
     int newPid = pid;
 
@@ -724,12 +693,6 @@
     int lowestPriorityPid;
     int lowestPriority;
     int callingPriority;
-
-    // Before looking into other processes, check if we have clients marked for
-    // pending removal in the same process.
-    if (getBiggestClient_l(callingPid, type, client, true /* pendingRemovalOnly */)) {
-        return true;
-    }
     if (!getPriority_l(callingPid, &callingPriority)) {
         ALOGE("getLowestPriorityBiggestClient_l: can't get process priority for pid %d",
                 callingPid);
@@ -798,8 +761,7 @@
 }
 
 bool ResourceManagerService::getBiggestClient_l(
-        int pid, MediaResource::Type type, std::shared_ptr<IResourceManagerClient> *client,
-        bool pendingRemovalOnly) {
+        int pid, MediaResource::Type type, std::shared_ptr<IResourceManagerClient> *client) {
     ssize_t index = mMap.indexOfKey(pid);
     if (index < 0) {
         ALOGE("getBiggestClient_l: can't find resource info for pid %d", pid);
@@ -811,9 +773,6 @@
     const ResourceInfos &infos = mMap.valueAt(index);
     for (size_t i = 0; i < infos.size(); ++i) {
         const ResourceList &resources = infos[i].resources;
-        if (pendingRemovalOnly && !infos[i].pendingRemoval) {
-            continue;
-        }
         for (auto it = resources.begin(); it != resources.end(); it++) {
             const MediaResourceParcel &resource = it->second;
             if (resource.type == type) {
diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h
index ee982b7..f500c62 100644
--- a/services/mediaresourcemanager/ResourceManagerService.h
+++ b/services/mediaresourcemanager/ResourceManagerService.h
@@ -18,8 +18,6 @@
 #ifndef ANDROID_MEDIA_RESOURCEMANAGERSERVICE_H
 #define ANDROID_MEDIA_RESOURCEMANAGERSERVICE_H
 
-#include <map>
-
 #include <aidl/android/media/BnResourceManagerService.h>
 #include <arpa/inet.h>
 #include <media/MediaResource.h>
@@ -52,7 +50,6 @@
     std::shared_ptr<IResourceManagerClient> client;
     sp<DeathNotifier> deathNotifier;
     ResourceList resources;
-    bool pendingRemoval{false};
 };
 
 // TODO: convert these to std::map
@@ -125,8 +122,6 @@
             int originalPid,
             int newPid) override;
 
-    Status markClientForPendingRemoval(int32_t pid, int64_t clientId) override;
-
     Status removeResource(int pid, int64_t clientId, bool checkValid);
 
 private:
@@ -151,8 +146,7 @@
     // Gets the client who owns biggest piece of specified resource type from pid.
     // Returns false if failed. The client will remain unchanged if failed.
     bool getBiggestClient_l(int pid, MediaResource::Type type,
-            std::shared_ptr<IResourceManagerClient> *client,
-            bool pendingRemovalOnly = false);
+            std::shared_ptr<IResourceManagerClient> *client);
 
     bool isCallingPriorityHigher_l(int callingPid, int pid);
 
diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
index 702935d..5d839fa 100644
--- a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
+++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp
@@ -472,56 +472,6 @@
         }
     }
 
-    void testMarkClientForPendingRemoval() {
-        bool result;
-
-        {
-            addResource();
-            mService->mSupportsSecureWithNonSecureCodec = true;
-
-            std::vector<MediaResourceParcel> resources;
-            resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
-
-            // Remove low priority clients
-            mService->removeClient(kTestPid1, getId(mTestClient1));
-
-            // no lower priority client
-            CHECK_STATUS_FALSE(mService->reclaimResource(kTestPid2, resources, &result));
-            verifyClients(false /* c1 */, false /* c2 */, false /* c3 */);
-
-            mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
-
-            // client marked for pending removal from the same process got reclaimed
-            CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
-            verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
-
-            // clean up client 3 which still left
-            mService->removeClient(kTestPid2, getId(mTestClient3));
-        }
-
-        {
-            addResource();
-            mService->mSupportsSecureWithNonSecureCodec = true;
-
-            std::vector<MediaResourceParcel> resources;
-            resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
-
-            mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
-
-            // client marked for pending removal from the same process got reclaimed
-            // first, even though there are lower priority process
-            CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
-            verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
-
-            // lower priority client got reclaimed
-            CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
-            verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
-
-            // clean up client 3 which still left
-            mService->removeClient(kTestPid2, getId(mTestClient3));
-        }
-    }
-
     void testRemoveClient() {
         addResource();
 
@@ -950,8 +900,4 @@
     testOverridePid();
 }
 
-TEST_F(ResourceManagerServiceTest, markClientForPendingRemoval) {
-    testMarkClientForPendingRemoval();
-}
-
 } // namespace android