Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 88de22ff authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

libaudiohal: Allow late registration of HIDL HAL services

DevicesFactoryHalHidl registers a notification callback
with a service manager to get notified about registration
of new HAL services.

The specific code for the MSD HAL has been removed,
this HAL service is now handled using the added generic
mechanism.

Bug: 149854039
Test: make
Change-Id: I2f7f83dec11ac2390f674afd9e4451ef46dde04e
parent c0d04987
Loading
Loading
Loading
Loading
+90 −22
Original line number Diff line number Diff line
@@ -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");

    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);
        }
class ServiceNotificationListener : public IServiceNotification {
  public:
    explicit ServiceNotificationListener(sp<DevicesFactoryHalHidl> factory)
            : mFactory(factory) {}

    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*/);
        }
    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*/);
        return Void();
    }

  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 @@ static const char* idFromHal(const char *name, status_t* status) {
#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::openDevice(const char *name, sp<DeviceHalInterfa

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 @@ status_t DevicesFactoryHalHidl::getHalPids(std::vector<pid_t> *pids) {
    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
+17 −4
Original line number Diff line number Diff line
@@ -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 @@ namespace CPP_VERSION {
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 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;
};
+7 −0
Original line number Diff line number Diff line
@@ -44,6 +44,13 @@ status_t DevicesFactoryHalHybrid::getHalPids(std::vector<pid_t> *pids) {
    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() {
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,8 @@ class DevicesFactoryHalHybrid : public DevicesFactoryHalInterface

            status_t getHalPids(std::vector<pid_t> *pids) override;

            status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback) override;

  private:
    sp<DevicesFactoryHalInterface> mLocalFactory;
    sp<DevicesFactoryHalInterface> mHidlFactory;
+4 −0
Original line number Diff line number Diff line
@@ -37,6 +37,10 @@ class DevicesFactoryHalLocal : public DevicesFactoryHalInterface
                return INVALID_OPERATION;
            }

            status_t setCallbackOnce(sp<DevicesFactoryHalCallback> callback __unused) override {
                return INVALID_OPERATION;
            }

  private:
    friend class DevicesFactoryHalHybrid;

Loading