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

Commit 15d531d4 authored by Shunkai Yao's avatar Shunkai Yao Committed by Automerger Merge Worker
Browse files

Merge "Add effect AIDL version compatibility test in libAudioHal" into main am: 8309b620

parents 759487f9 8309b620
Loading
Loading
Loading
Loading
+33 −26
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ cc_defaults {
    ],
    header_libs: [
        "android.hardware.audio.common.util@all-versions",
    ]
    ],
}

cc_defaults {
@@ -71,7 +71,7 @@ cc_defaults {
    ],
    header_libs: [
        "libaudioclient_headers",
        "libaudiohal_headers"
        "libaudiohal_headers",
    ],
    defaults: [
        "latest_android_media_audio_common_types_cpp_export_shared",
@@ -86,7 +86,7 @@ cc_library_shared {
    name: "libaudiohal@5.0",
    defaults: [
        "libaudiohal_default",
        "libaudiohal_hidl_default"
        "libaudiohal_hidl_default",
    ],
    srcs: [
        ":audio_core_hal_client_sources",
@@ -105,14 +105,14 @@ cc_library_shared {
        "-DMAJOR_VERSION=5",
        "-DMINOR_VERSION=0",
        "-include common/all-versions/VersionMacro.h",
    ]
    ],
}

cc_library_shared {
    name: "libaudiohal@6.0",
    defaults: [
        "libaudiohal_default",
        "libaudiohal_hidl_default"
        "libaudiohal_hidl_default",
    ],
    srcs: [
        ":audio_core_hal_client_sources",
@@ -131,14 +131,14 @@ cc_library_shared {
        "-DMAJOR_VERSION=6",
        "-DMINOR_VERSION=0",
        "-include common/all-versions/VersionMacro.h",
    ]
    ],
}

cc_library_static {
    name: "libaudiohal.effect@7.0",
    defaults: [
        "libaudiohal_default",
        "libaudiohal_hidl_default"
        "libaudiohal_hidl_default",
    ],
    srcs: [
        ":audio_effect_hidl_hal_client_sources",
@@ -153,14 +153,14 @@ cc_library_static {
        "-DMAJOR_VERSION=7",
        "-DMINOR_VERSION=0",
        "-include common/all-versions/VersionMacro.h",
    ]
    ],
}

cc_library_shared {
    name: "libaudiohal@7.0",
    defaults: [
        "libaudiohal_default",
        "libaudiohal_hidl_default"
        "libaudiohal_hidl_default",
    ],
    srcs: [
        ":audio_core_hal_client_sources",
@@ -180,7 +180,7 @@ cc_library_shared {
        "-DMAJOR_VERSION=7",
        "-DMINOR_VERSION=0",
        "-include common/all-versions/VersionMacro.h",
    ]
    ],
}

cc_library_shared {
@@ -189,7 +189,7 @@ cc_library_shared {
        "latest_android_hardware_audio_core_sounddose_ndk_shared",
        "latest_android_hardware_audio_sounddose_ndk_shared",
        "libaudiohal_default",
        "libaudiohal_hidl_default"
        "libaudiohal_hidl_default",
    ],
    srcs: [
        ":audio_core_hal_client_sources",
@@ -216,7 +216,7 @@ cc_library_shared {
        "-DCOMMON_TYPES_MINOR_VERSION=0",
        "-DCORE_TYPES_MINOR_VERSION=0",
        "-include common/all-versions/VersionMacro.h",
    ]
    ],
}

cc_defaults {
@@ -261,9 +261,30 @@ cc_library_shared {
    ],
    srcs: [
        "DevicesFactoryHalEntry.cpp",
        "EffectsFactoryHalEntry.cpp",
        ":audio_effect_hal_aidl_src_files",
        ":core_audio_hal_aidl_src_files",
    ],
}

filegroup {
    name: "core_audio_hal_aidl_src_files",
    srcs: [
        "ConversionHelperAidl.cpp",
        "DeviceHalAidl.cpp",
        "DevicesFactoryHalAidl.cpp",
        "Hal2AidlMapper.cpp",
        "StreamHalAidl.cpp",
    ],
}

filegroup {
    name: "audio_effect_hal_aidl_src_files",
    srcs: [
        "EffectConversionHelperAidl.cpp",
        "EffectBufferHalAidl.cpp",
        "EffectHalAidl.cpp",
        "EffectsFactoryHalAidl.cpp",
        "effectsAidlConversion/AidlConversionAec.cpp",
        "effectsAidlConversion/AidlConversionAgc1.cpp",
        "effectsAidlConversion/AidlConversionAgc2.cpp",
@@ -280,21 +301,7 @@ cc_library_shared {
        "effectsAidlConversion/AidlConversionVendorExtension.cpp",
        "effectsAidlConversion/AidlConversionVirtualizer.cpp",
        "effectsAidlConversion/AidlConversionVisualizer.cpp",
        "EffectsFactoryHalAidl.cpp",
        "EffectsFactoryHalEntry.cpp",
        ":audio_effectproxy_src_files",
        ":core_audio_hal_aidl_src_files",
    ],
}

filegroup {
    name: "core_audio_hal_aidl_src_files",
    srcs: [
        "ConversionHelperAidl.cpp",
        "DeviceHalAidl.cpp",
        "DevicesFactoryHalAidl.cpp",
        "Hal2AidlMapper.cpp",
        "StreamHalAidl.cpp",
    ],
}

+11 −0
Original line number Diff line number Diff line
@@ -63,3 +63,14 @@ cc_test {
    ],
    header_libs: ["libaudiohalimpl_headers"],
}

cc_test {
    name: "EffectHalVersionCompatibilityTest",
    srcs: [
        "EffectHalVersionCompatibility_test.cpp",
        ":audio_effect_hal_aidl_src_files",
    ],
    defaults: ["libaudiohal_aidl_test_default"],
    header_libs: ["libaudiohalimpl_headers"],
    static_libs: ["libgmock"],
}
+319 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <cstddef>
#include <unordered_map>
#define LOG_TAG "EffectHalVersionCompatibilityTest"

#include <EffectHalAidl.h>
#include <aidl/android/hardware/audio/effect/IEffect.h>
#include <aidl/android/hardware/audio/effect/IFactory.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
#include <system/audio_aidl_utils.h>
#include <system/audio_config.h>
#include <system/audio_effects/audio_effects_utils.h>
#include <system/audio_effects/effect_uuid.h>
#include <utils/Log.h>

using aidl::android::hardware::audio::effect::CommandId;
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::IFactory;
using aidl::android::hardware::audio::effect::kReopenSupportedVersion;
using aidl::android::hardware::audio::effect::Parameter;
using aidl::android::hardware::audio::effect::Processing;
using aidl::android::hardware::audio::effect::State;
using aidl::android::media::audio::common::AudioUuid;
using android::OK;
using android::sp;
using android::effect::EffectHalAidl;
using testing::_;
using testing::Eq;

namespace {

/**
 * Maps of parameter and the version it was introduced.
 */
// parameters defined directly in the Parameter union, except Parameter::specific (defined in
// kParamIdEffectVersionMap).
static const std::unordered_map<Parameter::Tag, int /* version */> kParamTagVersionMap = {
        {Parameter::common, 1},         {Parameter::deviceDescription, 1},
        {Parameter::mode, 1},           {Parameter::source, 1},
        {Parameter::offload, 1},        {Parameter::volumeStereo, 1},
        {Parameter::sourceMetadata, 2}, {Parameter::sinkMetadata, 2},
};

// Map of the version a specific effect type introduction
// Id tags defined Parameter::Id union, except Parameter::Id::commonTag (defined in
// kParamTagVersionMap).
static const std::unordered_map<Parameter::Id::Tag, int /* version */> kParamIdEffectVersionMap = {
        {Parameter::Id::vendorEffectTag, 1},
        {Parameter::Id::acousticEchoCancelerTag, 1},
        {Parameter::Id::automaticGainControlV1Tag, 1},
        {Parameter::Id::automaticGainControlV2Tag, 1},
        {Parameter::Id::bassBoostTag, 1},
        {Parameter::Id::downmixTag, 1},
        {Parameter::Id::dynamicsProcessingTag, 1},
        {Parameter::Id::environmentalReverbTag, 1},
        {Parameter::Id::equalizerTag, 1},
        {Parameter::Id::hapticGeneratorTag, 1},
        {Parameter::Id::loudnessEnhancerTag, 1},
        {Parameter::Id::noiseSuppressionTag, 1},
        {Parameter::Id::presetReverbTag, 1},
        {Parameter::Id::virtualizerTag, 1},
        {Parameter::Id::visualizerTag, 1},
        {Parameter::Id::volumeTag, 1},
        {Parameter::Id::spatializerTag, 2},
};
// Tags defined Parameter::Specific union.
static const std::unordered_map<Parameter::Specific::Tag, int /* version */>
        kParamEffectVersionMap = {
                {Parameter::Specific::vendorEffect, 1},
                {Parameter::Specific::acousticEchoCanceler, 1},
                {Parameter::Specific::automaticGainControlV1, 1},
                {Parameter::Specific::automaticGainControlV2, 1},
                {Parameter::Specific::bassBoost, 1},
                {Parameter::Specific::downmix, 1},
                {Parameter::Specific::dynamicsProcessing, 1},
                {Parameter::Specific::environmentalReverb, 1},
                {Parameter::Specific::equalizer, 1},
                {Parameter::Specific::hapticGenerator, 1},
                {Parameter::Specific::loudnessEnhancer, 1},
                {Parameter::Specific::noiseSuppression, 1},
                {Parameter::Specific::presetReverb, 1},
                {Parameter::Specific::virtualizer, 1},
                {Parameter::Specific::visualizer, 1},
                {Parameter::Specific::volume, 1},
                {Parameter::Specific::spatializer, 2},
};

class MockFactory : public IFactory {
  public:
    explicit MockFactory(int version) : IFactory(), mVersion(version) {}
    MOCK_METHOD(ndk::ScopedAStatus, queryEffects,
                (const std::optional<AudioUuid>& in_type_uuid,
                 const std::optional<AudioUuid>& in_impl_uuid,
                 const std::optional<AudioUuid>& in_proxy_uuid,
                 std::vector<Descriptor>* _aidl_return),
                (override));

    MOCK_METHOD(ndk::ScopedAStatus, queryProcessing,
                (const std::optional<Processing::Type>& in_type,
                 std::vector<Processing>* _aidl_return),
                (override));

    MOCK_METHOD(ndk::ScopedAStatus, createEffect,
                (const AudioUuid& in_impl_uuid, std::shared_ptr<IEffect>* _aidl_return),
                (override));

    MOCK_METHOD(ndk::ScopedAStatus, destroyEffect, (const std::shared_ptr<IEffect>& in_handle),
                (override));

    ndk::ScopedAStatus getInterfaceVersion(int32_t* _aidl_return) {
        *_aidl_return = mVersion;
        return ndk::ScopedAStatus::ok();
    }

    // these must be implemented but won't be used in this testing
    ::ndk::SpAIBinder asBinder() { return ::ndk::SpAIBinder(); }
    bool isRemote() { return false; }
    ::ndk::ScopedAStatus getInterfaceHash(std::string*) { return ndk::ScopedAStatus::ok(); }

  private:
    const int mVersion;
};

class MockEffect : public IEffect {
  public:
    explicit MockEffect(int version) : IEffect(), mVersion(version) {}
    MOCK_METHOD(ndk::ScopedAStatus, open,
                (const Parameter::Common& common,
                 const std::optional<Parameter::Specific>& specific,
                 IEffect::OpenEffectReturn* ret),
                (override));
    MOCK_METHOD(ndk::ScopedAStatus, close, (), (override));
    MOCK_METHOD(binder_status_t, dump, (int fd, const char** args, uint32_t numArgs), (override));
    MOCK_METHOD(ndk::ScopedAStatus, command, (CommandId id), (override));
    MOCK_METHOD(ndk::ScopedAStatus, getState, (State * state), (override));
    MOCK_METHOD(ndk::ScopedAStatus, getDescriptor, (Descriptor * desc), (override));
    MOCK_METHOD(ndk::ScopedAStatus, destroy, (), ());

    // reopen introduced in version kReopenSupportedVersion
    ndk::ScopedAStatus reopen(IEffect::OpenEffectReturn*) override {
        return mVersion < kReopenSupportedVersion
                       ? ndk::ScopedAStatus::fromStatus(STATUS_UNKNOWN_TRANSACTION)
                       : ndk::ScopedAStatus::ok();
    }

    // for all parameters introduced
    ndk::ScopedAStatus setParameter(const Parameter& param) override {
        const auto paramTag = param.getTag();
        switch (paramTag) {
            case Parameter::common:
            case Parameter::deviceDescription:
            case Parameter::mode:
            case Parameter::source:
            case Parameter::offload:
            case Parameter::volumeStereo:
            case Parameter::sinkMetadata:
                FALLTHROUGH_INTENDED;
            case Parameter::sourceMetadata: {
                if (kParamTagVersionMap.find(paramTag) != kParamTagVersionMap.end() &&
                    kParamTagVersionMap.at(paramTag) >= mVersion) {
                    return ndk::ScopedAStatus::ok();
                }
                break;
            }
            case Parameter::specific: {
                // TODO
                break;
            }
        }
        return ndk::ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
    }

    /**
     * Only care about version compatibility here:
     * @return BAD_VALUE if a tag is not supported by current AIDL version.
     * @return OK if a tag is supported by current AIDL version.
     */
    ndk::ScopedAStatus getParameter(const Parameter::Id& id, Parameter*) override {
        const auto idTag = id.getTag();
        switch (idTag) {
            case Parameter::Id::commonTag: {
                const auto paramTag = id.get<Parameter::Id::commonTag>();
                if (kParamTagVersionMap.find(paramTag) != kParamTagVersionMap.end() &&
                    kParamTagVersionMap.at(paramTag) >= mVersion) {
                    return ndk::ScopedAStatus::ok();
                }
                break;
            }
            case Parameter::Id::vendorEffectTag:
            case Parameter::Id::acousticEchoCancelerTag:
            case Parameter::Id::automaticGainControlV1Tag:
            case Parameter::Id::automaticGainControlV2Tag:
            case Parameter::Id::bassBoostTag:
            case Parameter::Id::downmixTag:
            case Parameter::Id::dynamicsProcessingTag:
            case Parameter::Id::environmentalReverbTag:
            case Parameter::Id::equalizerTag:
            case Parameter::Id::hapticGeneratorTag:
            case Parameter::Id::loudnessEnhancerTag:
            case Parameter::Id::noiseSuppressionTag:
            case Parameter::Id::presetReverbTag:
            case Parameter::Id::virtualizerTag:
            case Parameter::Id::visualizerTag:
            case Parameter::Id::volumeTag:
                FALLTHROUGH_INTENDED;
            case Parameter::Id::spatializerTag: {
                if (kParamIdEffectVersionMap.find(idTag) != kParamIdEffectVersionMap.end() &&
                    kParamIdEffectVersionMap.at(idTag) >= mVersion) {
                    return ndk::ScopedAStatus::ok();
                }
                break;
            }
        }
        return ndk::ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
    }

    ndk::ScopedAStatus getInterfaceVersion(int32_t* _aidl_return) {
        *_aidl_return = mVersion;
        return ndk::ScopedAStatus::ok();
    }

    // these must be implemented but won't be used in this testing
    ::ndk::SpAIBinder asBinder() { return ::ndk::SpAIBinder(); }
    bool isRemote() { return false; }
    ::ndk::ScopedAStatus getInterfaceHash(std::string*) { return ndk::ScopedAStatus::ok(); }

  private:
    const int mVersion;
};

static const std::vector<AudioUuid> kTestParamUUIDs = {
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidAcousticEchoCanceler(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidAutomaticGainControlV1(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidAutomaticGainControlV2(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidBassBoost(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidDownmix(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidDynamicsProcessing(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidEnvReverb(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidEqualizer(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidNoiseSuppression(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidPresetReverb(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidSpatializer(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidVirtualizer(),
        ::aidl::android::hardware::audio::effect::getEffectTypeUuidVisualizer(),
        ::aidl::android::hardware::audio::effect::getEffectUuidNull(),
};
static const std::vector<int> kTestParamVersion = {1, 2};  // Effect AIDL HAL versions to test

enum ParamName { UUID, VERSION };
using TestParam = std::tuple<AudioUuid, int /* version */>;

class EffectHalVersionCompatibilityTest : public ::testing::TestWithParam<TestParam> {
  public:
    void SetUp() override {
        mMockFactory = ndk::SharedRefBase::make<MockFactory>(mVersion);
        ASSERT_NE(mMockFactory, nullptr);
        mMockEffect = ndk::SharedRefBase::make<MockEffect>(mVersion);
        ASSERT_NE(mMockEffect, nullptr);
        mEffectHalAidl = sp<EffectHalAidl>::make(mMockFactory, mMockEffect, 0, 0, mDesc, false);
        ASSERT_NE(mEffectHalAidl, nullptr);
    }

    void TearDown() override {
        EXPECT_CALL(*mMockFactory, destroyEffect(_));
        mEffectHalAidl.clear();
        mMockEffect.reset();
        mMockFactory.reset();
    }

  protected:
    const int mVersion = std::get<VERSION>(GetParam());
    const AudioUuid mTypeUuid = std::get<UUID>(GetParam());
    const Descriptor mDesc = {.common.id.type = mTypeUuid};
    std::shared_ptr<MockFactory> mMockFactory = nullptr;
    std::shared_ptr<MockEffect> mMockEffect = nullptr;
    sp<EffectHalAidl> mEffectHalAidl = nullptr;
};

TEST_P(EffectHalVersionCompatibilityTest, testEffectAidlHalCreateDestroy) {
    // do nothing
}

INSTANTIATE_TEST_SUITE_P(
        EffectHalVersionCompatibilityTestWithVersion, EffectHalVersionCompatibilityTest,
        ::testing::Combine(testing::ValuesIn(kTestParamUUIDs),
                           testing::ValuesIn(kTestParamVersion)),
        [](const testing::TestParamInfo<EffectHalVersionCompatibilityTest::ParamType>& info) {
            auto version = std::to_string(std::get<VERSION>(info.param));
            auto uuid = android::audio::utils::toString(std::get<UUID>(info.param));
            std::string name = "EffectHalVersionCompatibilityTest_V" + version + "_" + uuid;
            std::replace_if(
                    name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
            return name;
        });

}  // namespace
 No newline at end of file