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

Commit e5011000 authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

libaudiohal@aidl: Provide an example IHalAdapterVendorExtension

This service is necessary for any vendor because all vendor
HAL implementations have some vendor-specific parameters.
An example implementation is added, which is used by Cuttlefish.

Updated the framework client code to handle service crashes
and rebind automatically. This allows to avoid restarting
the audioserver when the parameter parser service crashes.

Bug: 321651892
Test: atest audiorouting_tests
Change-Id: Iabb983c11e581bd4d44798d2a3af6683f326546c
parent b1cb0b6a
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -37,10 +37,6 @@ status_t parseAndGetVendorParameters(
    using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
    if (parameterKeys.size() == 0) return OK;
    const String8 rawKeys = parameterKeys.keysToString();
    if (vendorExt == nullptr) {
        ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeys.c_str());
        return OK;
    }

    std::vector<std::string> parameterIds;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameterIds(
@@ -85,10 +81,6 @@ status_t parseAndSetVendorParameters(
    using ParameterScope = IHalAdapterVendorExtension::ParameterScope;
    if (parameters.size() == 0) return OK;
    const String8 rawKeysAndValues = parameters.toString();
    if (vendorExt == nullptr) {
        ALOGW("%s: unknown parameters, ignored: \"%s\"", __func__, rawKeysAndValues.c_str());
        return OK;
    }

    std::vector<VendorParameter> syncParameters, asyncParameters;
    RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(vendorExt->parseVendorParameters(
+5 −9
Original line number Diff line number Diff line
@@ -1024,15 +1024,11 @@ status_t DeviceHalAidl::filterAndUpdateBtA2dpParameters(AudioParameter &paramete
    (void)VALUE_OR_RETURN_STATUS(filterOutAndProcessParameter<String8>(
                    parameters, String8(AudioParameter::keyReconfigA2dp),
                    [&](const String8& value) -> status_t {
                        if (mVendorExt != nullptr) {
                        std::vector<VendorParameter> result;
                        RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
                                mVendorExt->parseBluetoothA2dpReconfigureOffload(
                                        std::string(value.c_str()), &result)));
                        reconfigureOffload = std::move(result);
                        } else {
                            reconfigureOffload = std::vector<VendorParameter>();
                        }
                        return OK;
                    }));
    if (mBluetoothA2dp != nullptr && a2dpEnabled.has_value()) {
+79 −16
Original line number Diff line number Diff line
@@ -17,12 +17,14 @@
#include <algorithm>
#include <map>
#include <memory>
#include <mutex>
#include <string>

#define LOG_TAG "DevicesFactoryHalAidl"
//#define LOG_NDEBUG 0

#include <aidl/android/hardware/audio/core/IModule.h>
#include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
#include <android/binder_manager.h>
#include <media/AidlConversionNdkCpp.h>
#include <media/AidlConversionUtil.h>
@@ -35,6 +37,7 @@ using aidl::android::aidl_utils::statusTFromBinderStatus;
using aidl::android::hardware::audio::core::IConfig;
using aidl::android::hardware::audio::core::IModule;
using aidl::android::hardware::audio::core::SurroundSoundConfig;
using aidl::android::hardware::audio::core::VendorParameter;
using aidl::android::media::audio::common::AudioHalEngineConfig;
using aidl::android::media::audio::IHalAdapterVendorExtension;
using android::detail::AudioHalVersionInfo;
@@ -62,10 +65,84 @@ ndk2cpp_SurroundSoundConfig(const SurroundSoundConfig& ndk) {
    return cpp;
}

class HalAdapterVendorExtensionWrapper :
            public ::aidl::android::media::audio::BnHalAdapterVendorExtension {
  private:
    template<typename F>
    ndk::ScopedAStatus callWithRetryOnCrash(F method) {
        ndk::ScopedAStatus status = ndk::ScopedAStatus::ok();
        for (auto service = getService(); service != nullptr; service = getService(true)) {
            status = method(service);
            if (status.getStatus() != STATUS_DEAD_OBJECT) break;
        }
        return status;
    }

    ndk::ScopedAStatus parseVendorParameterIds(ParameterScope in_scope,
                                               const std::string& in_rawKeys,
                                               std::vector<std::string>* _aidl_return) override {
        return callWithRetryOnCrash([&](auto service) {
            return service->parseVendorParameterIds(in_scope, in_rawKeys, _aidl_return);
        });
    }

    ndk::ScopedAStatus parseVendorParameters(
            ParameterScope in_scope, const std::string& in_rawKeysAndValues,
            std::vector<VendorParameter>* out_syncParameters,
            std::vector<VendorParameter>* out_asyncParameters) override {
        return callWithRetryOnCrash([&](auto service) {
            return service->parseVendorParameters(in_scope, in_rawKeysAndValues,
                    out_syncParameters, out_asyncParameters);
        });
    }

    ndk::ScopedAStatus parseBluetoothA2dpReconfigureOffload(
            const std::string& in_rawValue, std::vector<VendorParameter>* _aidl_return) override {
        return callWithRetryOnCrash([&](auto service) {
            return service->parseBluetoothA2dpReconfigureOffload(in_rawValue, _aidl_return);
        });
    }

    ndk::ScopedAStatus parseBluetoothLeReconfigureOffload(const std::string& in_rawValue,
            std::vector<VendorParameter>* _aidl_return) override {
        return callWithRetryOnCrash([&](auto service) {
            return service->parseBluetoothLeReconfigureOffload(in_rawValue, _aidl_return);
        });
    }

    ndk::ScopedAStatus processVendorParameters(ParameterScope in_scope,
                                               const std::vector<VendorParameter>& in_parameters,
                                               std::string* _aidl_return) override {
        return callWithRetryOnCrash([&](auto service) {
            return service->processVendorParameters(in_scope, in_parameters, _aidl_return);
        });
    }

    std::shared_ptr<IHalAdapterVendorExtension> getService(bool reset = false) {
        std::lock_guard l(mLock);
        if (reset || !mVendorExt.has_value()) {
            auto serviceName = std::string(IHalAdapterVendorExtension::descriptor) + "/default";
            if (AServiceManager_isDeclared(serviceName.c_str())) {
                mVendorExt = std::shared_ptr<IHalAdapterVendorExtension>(
                        IHalAdapterVendorExtension::fromBinder(ndk::SpAIBinder(
                                        AServiceManager_waitForService(serviceName.c_str()))));
            } else {
                mVendorExt = nullptr;
            }
        }
        return mVendorExt.value();
    }

    std::mutex mLock;
    std::optional<std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>>
            mVendorExt GUARDED_BY(mLock);
};

}  // namespace

DevicesFactoryHalAidl::DevicesFactoryHalAidl(std::shared_ptr<IConfig> config)
    : mConfig(std::move(config)) {
        : mConfig(std::move(config)),
          mVendorExt(ndk::SharedRefBase::make<HalAdapterVendorExtensionWrapper>()) {
}

status_t DevicesFactoryHalAidl::getDeviceNames(std::vector<std::string> *names) {
@@ -110,7 +187,7 @@ status_t DevicesFactoryHalAidl::openDevice(const char *name, sp<DeviceHalInterfa
        ALOGE("%s fromBinder %s failed", __func__, serviceName.c_str());
        return NO_INIT;
    }
    *device = sp<DeviceHalAidl>::make(name, service, getVendorExtension());
    *device = sp<DeviceHalAidl>::make(name, service, mVendorExt);
    return OK;
}

@@ -149,20 +226,6 @@ status_t DevicesFactoryHalAidl::getEngineConfig(
    return OK;
}

std::shared_ptr<IHalAdapterVendorExtension> DevicesFactoryHalAidl::getVendorExtension() {
    if (!mVendorExt.has_value()) {
        auto serviceName = std::string(IHalAdapterVendorExtension::descriptor) + "/default";
        if (AServiceManager_isDeclared(serviceName.c_str())) {
            mVendorExt = std::shared_ptr<IHalAdapterVendorExtension>(
                    IHalAdapterVendorExtension::fromBinder(ndk::SpAIBinder(
                                    AServiceManager_waitForService(serviceName.c_str()))));
        } else {
            mVendorExt = nullptr;
        }
    }
    return mVendorExt.value();
}

// Main entry-point to the shared library.
extern "C" __attribute__((visibility("default"))) void* createIDevicesFactoryImpl() {
    auto serviceName = std::string(IConfig::descriptor) + "/default";
+1 −4
Original line number Diff line number Diff line
@@ -45,10 +45,7 @@ class DevicesFactoryHalAidl : public DevicesFactoryHalInterface

  private:
    const std::shared_ptr<::aidl::android::hardware::audio::core::IConfig> mConfig;
    std::optional<std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension>>
            mVendorExt;

    std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> getVendorExtension();
    const std::shared_ptr<::aidl::android::media::audio::IHalAdapterVendorExtension> mVendorExt;

    ~DevicesFactoryHalAidl() = default;
};
+0 −15
Original line number Diff line number Diff line
@@ -443,21 +443,6 @@ TEST_F(DeviceHalAidlTest, ScreenRotation) {
    EXPECT_EQ(ScreenRotation::DEG_0, mModule->getScreenRotation());
}

// Without a vendor extension, any unrecognized parameters must be ignored.
TEST_F(DeviceHalAidlTest, VendorParameterIgnored) {
    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
    EXPECT_EQ(0UL, mModule->getSyncParameters().size());
    EXPECT_EQ(OK, mDevice->setParameters(createParameterString("random_name", "random_value")));
    EXPECT_EQ(0UL, mModule->getAsyncParameters().size());
    EXPECT_EQ(0UL, mModule->getSyncParameters().size());

    EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
    String8 values;
    EXPECT_EQ(OK, mDevice->getParameters(String8("random_name"), &values));
    EXPECT_EQ(0UL, mModule->getRetrievedParameterIds().size());
    EXPECT_EQ(0UL, values.length());
}

class DeviceHalAidlVendorParametersTest : public testing::Test {
  public:
    void SetUp() override {
Loading