mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-02 06:22:53 +00:00
AIDL effect: Add vts for the initial effect AIDL interface implementation am: 67b1be60ab
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2198793 Change-Id: I26428d4b3eb3e3b1caed9761799755b62ad1fdea Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -41,3 +41,31 @@ cc_test {
|
||||
"vts",
|
||||
],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "VtsHalAudioEffectTargetTest",
|
||||
defaults: [
|
||||
"VtsHalTargetTestDefaults",
|
||||
"use_libaidlvintf_gtest_helper_static",
|
||||
],
|
||||
srcs: [
|
||||
"VtsHalAudioEffectTargetTest.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbinder_ndk",
|
||||
],
|
||||
static_libs: [
|
||||
"android.media.audio.common.types-V1-ndk",
|
||||
"android.hardware.audio.effect-V1-ndk",
|
||||
],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
"-Wthread-safety",
|
||||
],
|
||||
test_suites: [
|
||||
"general-tests",
|
||||
"vts",
|
||||
],
|
||||
}
|
||||
|
||||
99
audio/aidl/vts/AudioHalBinderServiceUtil.h
Normal file
99
audio/aidl/vts/AudioHalBinderServiceUtil.h
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include <android-base/properties.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
class AudioHalBinderServiceUtil {
|
||||
public:
|
||||
ndk::SpAIBinder connectToService(const std::string& serviceName) {
|
||||
mServiceName = serviceName;
|
||||
mBinder = ndk::SpAIBinder(AServiceManager_getService(serviceName.c_str()));
|
||||
if (mBinder == nullptr) {
|
||||
LOG(ERROR) << "Failed to get service " << serviceName;
|
||||
} else {
|
||||
LOG(DEBUG) << "succeed to get service " << serviceName;
|
||||
}
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
ndk::SpAIBinder restartService(
|
||||
std::chrono::milliseconds timeoutMs = std::chrono::milliseconds(3000)) {
|
||||
mDeathHandler.reset(new AidlDeathRecipient(mBinder));
|
||||
if (STATUS_OK != mDeathHandler->linkToDeath()) {
|
||||
LOG(ERROR) << "linkToDeath failed";
|
||||
return nullptr;
|
||||
}
|
||||
if (!android::base::SetProperty("sys.audio.restart.hal", "1")) {
|
||||
LOG(ERROR) << "SetProperty failed";
|
||||
return nullptr;
|
||||
}
|
||||
if (!mDeathHandler->waitForFired(timeoutMs)) {
|
||||
LOG(ERROR) << "Timeout wait for death";
|
||||
return nullptr;
|
||||
}
|
||||
mDeathHandler.reset();
|
||||
return connectToService(mServiceName);
|
||||
}
|
||||
|
||||
private:
|
||||
class AidlDeathRecipient {
|
||||
public:
|
||||
explicit AidlDeathRecipient(const ndk::SpAIBinder& binder)
|
||||
: binder(binder), recipient(AIBinder_DeathRecipient_new(&binderDiedCallbackAidl)) {}
|
||||
|
||||
binder_status_t linkToDeath() {
|
||||
return AIBinder_linkToDeath(binder.get(), recipient.get(), this);
|
||||
}
|
||||
|
||||
bool waitForFired(std::chrono::milliseconds timeoutMs) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
condition.wait_for(lock, timeoutMs, [this]() { return fired; });
|
||||
return fired;
|
||||
}
|
||||
|
||||
private:
|
||||
const ndk::SpAIBinder binder;
|
||||
const ndk::ScopedAIBinder_DeathRecipient recipient;
|
||||
std::mutex mutex;
|
||||
std::condition_variable condition;
|
||||
bool fired = false;
|
||||
|
||||
void binderDied() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
fired = true;
|
||||
condition.notify_one();
|
||||
};
|
||||
|
||||
static void binderDiedCallbackAidl(void* cookie) {
|
||||
AidlDeathRecipient* self = static_cast<AidlDeathRecipient*>(cookie);
|
||||
self->binderDied();
|
||||
}
|
||||
};
|
||||
|
||||
std::string mServiceName;
|
||||
ndk::SpAIBinder mBinder;
|
||||
std::unique_ptr<AidlDeathRecipient> mDeathHandler;
|
||||
};
|
||||
@@ -15,10 +15,8 @@
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <condition_variable>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
@@ -35,11 +33,9 @@
|
||||
#include <aidl/android/media/audio/common/AudioIoFlags.h>
|
||||
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
|
||||
#include <android-base/chrono_utils.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include "AudioHalBinderServiceUtil.h"
|
||||
#include "ModuleConfig.h"
|
||||
|
||||
using namespace android;
|
||||
@@ -101,38 +97,20 @@ AudioDeviceAddress GenerateUniqueDeviceAddress() {
|
||||
return AudioDeviceAddress::make<AudioDeviceAddress::Tag::id>(std::to_string(++nextId));
|
||||
}
|
||||
|
||||
struct AidlDeathRecipient {
|
||||
const ndk::SpAIBinder binder;
|
||||
const ndk::ScopedAIBinder_DeathRecipient recipient;
|
||||
std::mutex mutex;
|
||||
std::condition_variable condition;
|
||||
bool fired = false;
|
||||
|
||||
explicit AidlDeathRecipient(const ndk::SpAIBinder& binder)
|
||||
: binder(binder), recipient(AIBinder_DeathRecipient_new(&binderDiedCallbackAidl)) {}
|
||||
|
||||
binder_status_t linkToDeath() {
|
||||
return AIBinder_linkToDeath(binder.get(), recipient.get(), this);
|
||||
}
|
||||
|
||||
void binderDied() {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
fired = true;
|
||||
condition.notify_one();
|
||||
};
|
||||
|
||||
bool waitForFired(int timeoutMs) {
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
condition.wait_for(lock, std::chrono::milliseconds(timeoutMs), [this]() { return fired; });
|
||||
return fired;
|
||||
}
|
||||
|
||||
static void binderDiedCallbackAidl(void* cookie) {
|
||||
AidlDeathRecipient* self = static_cast<AidlDeathRecipient*>(cookie);
|
||||
self->binderDied();
|
||||
}
|
||||
template <typename T>
|
||||
struct IsInput {
|
||||
constexpr operator bool() const;
|
||||
};
|
||||
|
||||
template <>
|
||||
constexpr IsInput<IStreamIn>::operator bool() const {
|
||||
return true;
|
||||
}
|
||||
template <>
|
||||
constexpr IsInput<IStreamOut>::operator bool() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// All 'With*' classes are move-only because they are associated with some
|
||||
// resource or state of a HAL module.
|
||||
class WithDebugFlags {
|
||||
@@ -238,20 +216,15 @@ class AudioCoreModule : public testing::TestWithParam<std::string> {
|
||||
}
|
||||
|
||||
void ConnectToService() {
|
||||
module = IModule::fromBinder(
|
||||
ndk::SpAIBinder(AServiceManager_getService(GetParam().c_str())));
|
||||
module = IModule::fromBinder(binderUtil.connectToService(GetParam()));
|
||||
ASSERT_NE(module, nullptr);
|
||||
}
|
||||
|
||||
void RestartService() {
|
||||
ASSERT_NE(module, nullptr);
|
||||
moduleConfig.reset();
|
||||
deathHandler.reset(new AidlDeathRecipient(module->asBinder()));
|
||||
ASSERT_EQ(STATUS_OK, deathHandler->linkToDeath());
|
||||
ASSERT_TRUE(base::SetProperty("sys.audio.restart.hal", "1"));
|
||||
EXPECT_TRUE(deathHandler->waitForFired(3000));
|
||||
deathHandler.reset();
|
||||
ASSERT_NO_FATAL_FAILURE(ConnectToService());
|
||||
module = IModule::fromBinder(binderUtil.restartService());
|
||||
ASSERT_NE(module, nullptr);
|
||||
}
|
||||
|
||||
void ApplyEveryConfig(const std::vector<AudioPortConfig>& configs) {
|
||||
@@ -322,8 +295,8 @@ class AudioCoreModule : public testing::TestWithParam<std::string> {
|
||||
}
|
||||
|
||||
std::shared_ptr<IModule> module;
|
||||
std::unique_ptr<AidlDeathRecipient> deathHandler;
|
||||
std::unique_ptr<ModuleConfig> moduleConfig;
|
||||
AudioHalBinderServiceUtil binderUtil;
|
||||
WithDebugFlags debug;
|
||||
};
|
||||
|
||||
|
||||
130
audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
Normal file
130
audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 <string>
|
||||
|
||||
#define LOG_TAG "VtsHalAudioEffect"
|
||||
|
||||
#include <aidl/Gtest.h>
|
||||
#include <aidl/Vintf.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android/binder_interface_utils.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/IFactory.h>
|
||||
|
||||
#include "AudioHalBinderServiceUtil.h"
|
||||
|
||||
using namespace android;
|
||||
|
||||
using ndk::ScopedAStatus;
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::IFactory;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
namespace ndk {
|
||||
std::ostream& operator<<(std::ostream& str, const ScopedAStatus& status) {
|
||||
str << status.getDescription();
|
||||
return str;
|
||||
}
|
||||
} // namespace ndk
|
||||
|
||||
class EffectFactory : public testing::TestWithParam<std::string> {
|
||||
public:
|
||||
void SetUp() override { ASSERT_NO_FATAL_FAILURE(ConnectToService()); }
|
||||
|
||||
void TearDown() override {}
|
||||
|
||||
void ConnectToService() {
|
||||
serviceName = GetParam();
|
||||
factory = IFactory::fromBinder(binderUtil.connectToService(serviceName));
|
||||
ASSERT_NE(factory, nullptr);
|
||||
}
|
||||
|
||||
void RestartService() {
|
||||
ASSERT_NE(factory, nullptr);
|
||||
factory = IFactory::fromBinder(binderUtil.restartService());
|
||||
ASSERT_NE(factory, nullptr);
|
||||
}
|
||||
|
||||
std::shared_ptr<IFactory> factory;
|
||||
std::string serviceName;
|
||||
AudioHalBinderServiceUtil binderUtil;
|
||||
// TODO: these UUID can get from config file
|
||||
// ec7178ec-e5e1-4432-a3f4-4657e6795210
|
||||
const AudioUuid nullUuid = {static_cast<int32_t>(0xec7178ec),
|
||||
0xe5e1,
|
||||
0x4432,
|
||||
0xa3f4,
|
||||
{0x46, 0x57, 0xe6, 0x79, 0x52, 0x10}};
|
||||
const AudioUuid zeroUuid = {
|
||||
static_cast<int32_t>(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
};
|
||||
|
||||
TEST_P(EffectFactory, SetupAndTearDown) {
|
||||
// Intentionally empty test body.
|
||||
}
|
||||
|
||||
TEST_P(EffectFactory, CanBeRestarted) {
|
||||
ASSERT_NO_FATAL_FAILURE(RestartService());
|
||||
}
|
||||
|
||||
TEST_P(EffectFactory, QueriedDescriptorList) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
ScopedAStatus status = factory->queryEffects(std::nullopt, std::nullopt, &descriptors);
|
||||
EXPECT_EQ(EX_NONE, status.getExceptionCode());
|
||||
EXPECT_NE(static_cast<int>(descriptors.size()), 0);
|
||||
}
|
||||
|
||||
TEST_P(EffectFactory, DescriptorUUIDNotNull) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
ScopedAStatus status = factory->queryEffects(std::nullopt, std::nullopt, &descriptors);
|
||||
EXPECT_EQ(EX_NONE, status.getExceptionCode());
|
||||
// TODO: Factory eventually need to return the full list of MUST supported AOSP effects.
|
||||
for (auto& desc : descriptors) {
|
||||
EXPECT_NE(desc.type, zeroUuid);
|
||||
EXPECT_NE(desc.uuid, zeroUuid);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(EffectFactory, QueriedDescriptorNotExistType) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
ScopedAStatus status = factory->queryEffects(nullUuid, std::nullopt, &descriptors);
|
||||
EXPECT_EQ(EX_NONE, status.getExceptionCode());
|
||||
EXPECT_EQ(static_cast<int>(descriptors.size()), 0);
|
||||
}
|
||||
|
||||
TEST_P(EffectFactory, QueriedDescriptorNotExistInstance) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
ScopedAStatus status = factory->queryEffects(std::nullopt, nullUuid, &descriptors);
|
||||
EXPECT_EQ(EX_NONE, status.getExceptionCode());
|
||||
EXPECT_EQ(static_cast<int>(descriptors.size()), 0);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactory,
|
||||
testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
|
||||
android::PrintInstanceNameToString);
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EffectFactory);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(1);
|
||||
ABinderProcess_startThreadPool();
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
Reference in New Issue
Block a user