diff --git a/audio/6.0/IDevice.hal b/audio/6.0/IDevice.hal index 42a545b0be..e885fe2267 100644 --- a/audio/6.0/IDevice.hal +++ b/audio/6.0/IDevice.hal @@ -260,7 +260,8 @@ interface IDevice { /** * Returns an array with available microphones in device. * - * @return retval INVALID_STATE if the call is not successful, + * @return retval NOT_SUPPORTED if there are no microphones on this device + * INVALID_STATE if the call is not successful, * OK otherwise. * * @return microphones array with microphones info diff --git a/audio/6.0/IStream.hal b/audio/6.0/IStream.hal index f4c91f826d..451e1162bf 100644 --- a/audio/6.0/IStream.hal +++ b/audio/6.0/IStream.hal @@ -123,9 +123,11 @@ interface IStream { * equivalent to getting AUDIO_PARAMETER_STREAM_SUP_FORMATS on the legacy * HAL. * + * @return retval operation completion status. * @return formats supported audio formats. + * Must be non empty if retval is OK. */ - getSupportedFormats() generates (vec formats); + getSupportedFormats() generates (Result retval, vec formats); /** * Sets the audio format of the stream. Calling this method is equivalent to diff --git a/audio/common/all-versions/test/utility/include/utility/EnvironmentTearDown.h b/audio/common/all-versions/test/utility/include/utility/EnvironmentTearDown.h index 0e416f3c64..2b240ce309 100644 --- a/audio/common/all-versions/test/utility/include/utility/EnvironmentTearDown.h +++ b/audio/common/all-versions/test/utility/include/utility/EnvironmentTearDown.h @@ -20,9 +20,6 @@ #include #include -#include -#include - namespace android { namespace hardware { namespace audio { @@ -34,18 +31,20 @@ namespace utility { * Avoid destroying static objects after main return. * Post main return destruction leads to incorrect gtest timing measurements as * well as harder debuging if anything goes wrong during destruction. */ -class Environment : public ::testing::VtsHalHidlTargetTestEnvBase { - public: +class EnvironmentTearDown { + public: using TearDownFunc = std::function; void registerTearDown(TearDownFunc&& tearDown) { tearDowns.push_front(std::move(tearDown)); } - private: - void HidlTearDown() override { + protected: + void executeAllTearDowns() { // Call the tear downs in reverse order of insertion for (auto& tearDown : tearDowns) { tearDown(); } } + + private: std::list tearDowns; }; diff --git a/audio/core/all-versions/default/Stream.cpp b/audio/core/all-versions/default/Stream.cpp index e62f6d3b0a..5f24a5d781 100644 --- a/audio/core/all-versions/default/Stream.cpp +++ b/audio/core/all-versions/default/Stream.cpp @@ -175,8 +175,17 @@ Return Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb) { for (size_t i = 0; i < halFormats.size(); ++i) { formats[i] = AudioFormat(halFormats[i]); } + // Legacy get_parameter does not return a status_t, thus can not advertise of failure. + // Note that the method must not return an empty list if this capability is supported. + if (formats.size() == 0) { + result = Result::NOT_SUPPORTED; + } } +#if MAJOR_VERSION <= 5 _hidl_cb(formats); +#elif MAJOR_VERSION >= 6 + _hidl_cb(result, formats); +#endif return Void(); } diff --git a/audio/core/all-versions/vts/functional/2.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/2.0/AudioPrimaryHidlHalTest.cpp index 7906bf1b62..c1894645fd 100644 --- a/audio/core/all-versions/vts/functional/2.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/2.0/AudioPrimaryHidlHalTest.cpp @@ -60,19 +60,20 @@ TEST_IO_STREAM(SetConnectedState, "deconnection", testConnectedState(stream.get())) -TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail", ASSERT_IS_OK(device->getHwAvSync())); +TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail", + ASSERT_IS_OK(getDevice()->getHwAvSync())); -TEST_F(AudioPrimaryHidlTest, setMode) { +TEST_P(AudioPrimaryHidlTest, setMode) { doc::test("Make sure setMode always succeeds if mode is valid and fails otherwise"); // Test Invalid values for (AudioMode mode : {AudioMode::INVALID, AudioMode::CURRENT, AudioMode::CNT}) { SCOPED_TRACE("mode=" + toString(mode)); - ASSERT_RESULT(Result::INVALID_ARGUMENTS, device->setMode(mode)); + ASSERT_RESULT(Result::INVALID_ARGUMENTS, getDevice()->setMode(mode)); } // Test valid values for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION, AudioMode::RINGTONE, AudioMode::NORMAL /* Make sure to leave the test in normal mode */}) { SCOPED_TRACE("mode=" + toString(mode)); - ASSERT_OK(device->setMode(mode)); + ASSERT_OK(getDevice()->setMode(mode)); } } diff --git a/audio/core/all-versions/vts/functional/2.0/EnvironmentTearDown.h b/audio/core/all-versions/vts/functional/2.0/EnvironmentTearDown.h new file mode 100644 index 0000000000..6373e39111 --- /dev/null +++ b/audio/core/all-versions/vts/functional/2.0/EnvironmentTearDown.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 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. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_CORE_2_0_ENVIRONMENT_TEARDOWN_H +#define ANDROID_HARDWARE_AUDIO_CORE_2_0_ENVIRONMENT_TEARDOWN_H + +#include +#include + +#include "utility/EnvironmentTearDown.h" + +class Environment : public ::android::hardware::audio::common::test::utility::EnvironmentTearDown, + public ::testing::VtsHalHidlTargetTestEnvBase { + private: + void HidlTearDown() override { + executeAllTearDowns(); + VtsHalHidlTargetTestEnvBase::HidlTearDown(); + } +}; + +#endif // ANDROID_HARDWARE_AUDIO_CORE_2_0_ENVIRONMENT_TEARDOWN_H diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp index 15be3bf470..e267a5ea72 100644 --- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalTest.cpp @@ -16,28 +16,18 @@ #include "AudioPrimaryHidlHalTest.h" -static void waitForDeviceDestruction() { - // FIXME: there is no way to know when the remote IDevice is being destroyed - // Binder does not support testing if an object is alive, thus - // wait for 100ms to let the binder destruction propagates and - // the remote device has the time to be destroyed. - // flushCommand makes sure all local command are sent, thus should reduce - // the latency between local and remote destruction. - IPCThreadState::self()->flushCommands(); - usleep(100 * 1000); -} - -TEST_F(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) { +TEST_P(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) { doc::test("Calling openDevice(\"primary\") should return the primary device."); + if (getDeviceName() != DeviceManager::kPrimaryDevice) { + GTEST_SKIP() << "No primary device on this factory"; // returns + } + struct WaitExecutor { - ~WaitExecutor() { waitForDeviceDestruction(); } + ~WaitExecutor() { DeviceManager::waitForInstanceDestruction(); } } waitExecutor; // Make sure we wait for the device destruction on exiting from the test. Result result; sp baseDevice; - ASSERT_OK(devicesFactory->openDevice("primary", returnIn(result, baseDevice))); - if (result != Result::OK && isPrimaryDeviceOptional()) { - GTEST_SKIP() << "No primary device on this factory"; // returns - } + ASSERT_OK(getDevicesFactory()->openDevice("primary", returnIn(result, baseDevice))); ASSERT_OK(result); ASSERT_TRUE(baseDevice != nullptr); @@ -50,10 +40,13 @@ TEST_F(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) { /////////////////////////// get(Active)Microphones /////////////////////////// ////////////////////////////////////////////////////////////////////////////// -TEST_F(AudioPrimaryHidlTest, GetMicrophonesTest) { +TEST_P(AudioHidlDeviceTest, GetMicrophonesTest) { doc::test("Make sure getMicrophones always succeeds"); hidl_vec microphones; - ASSERT_OK(device->getMicrophones(returnIn(res, microphones))); + ASSERT_OK(getDevice()->getMicrophones(returnIn(res, microphones))); + if (res == Result::NOT_SUPPORTED) { + GTEST_SKIP() << "getMicrophones is not supported"; // returns + } ASSERT_OK(res); if (microphones.size() > 0) { // When there is microphone on the phone, try to open an input stream @@ -75,15 +68,15 @@ TEST_F(AudioPrimaryHidlTest, GetMicrophonesTest) { } sp stream; AudioConfig suggestedConfig{}; - ASSERT_OK(device->openInputStream(ioHandle, microphone.deviceAddress, config, flags, - initMetadata, - returnIn(res, stream, suggestedConfig))); + ASSERT_OK(getDevice()->openInputStream(ioHandle, microphone.deviceAddress, config, + flags, initMetadata, + returnIn(res, stream, suggestedConfig))); if (res != Result::OK) { ASSERT_TRUE(stream == nullptr); AudioConfig suggestedConfigRetry{}; - ASSERT_OK(device->openInputStream(ioHandle, microphone.deviceAddress, - suggestedConfig, flags, initMetadata, - returnIn(res, stream, suggestedConfigRetry))); + ASSERT_OK(getDevice()->openInputStream( + ioHandle, microphone.deviceAddress, suggestedConfig, flags, initMetadata, + returnIn(res, stream, suggestedConfigRetry))); } ASSERT_OK(res); hidl_vec activeMicrophones; @@ -131,7 +124,7 @@ TEST_F(AudioPrimaryHidlTest, GetMicrophonesTest) { } } -TEST_F(AudioPrimaryHidlTest, SetConnectedState) { +TEST_P(AudioHidlDeviceTest, SetConnectedState) { doc::test("Check that the HAL can be notified of device connection and deconnection"); using AD = AudioDevice; for (auto deviceType : {AD::OUT_HDMI, AD::OUT_WIRED_HEADPHONE, AD::IN_USB_HEADSET}) { @@ -140,7 +133,7 @@ TEST_F(AudioPrimaryHidlTest, SetConnectedState) { SCOPED_TRACE("state=" + ::testing::PrintToString(state)); DeviceAddress address = {}; address.device = deviceType; - auto ret = device->setConnectedState(address, state); + auto ret = getDevice()->setConnectedState(address, state); ASSERT_TRUE(ret.isOk()); if (ret == Result::NOT_SUPPORTED) { doc::partialTest("setConnectedState is not supported"); @@ -153,9 +146,7 @@ TEST_F(AudioPrimaryHidlTest, SetConnectedState) { // Because there is no way of knowing if the devices were connected before // calling setConnectedState, there is no way to restore the HAL to its // initial state. To workaround this, destroy the HAL at the end of this test. - device.clear(); - waitForDeviceDestruction(); - ASSERT_NO_FATAL_FAILURE(initPrimaryDevice()); + ASSERT_TRUE(resetDevice()); } static void testGetDevices(IStream* stream, AudioDevice expectedDevice) { @@ -181,9 +172,10 @@ static void testSetDevices(IStream* stream, const DeviceAddress& address) { DeviceAddress otherAddress = address; otherAddress.device = (address.device & AudioDevice::BIT_IN) == 0 ? AudioDevice::OUT_SPEAKER : AudioDevice::IN_BUILTIN_MIC; - EXPECT_OK(stream->setDevices({otherAddress})); + EXPECT_RESULT(okOrNotSupported, stream->setDevices({otherAddress})); - ASSERT_OK(stream->setDevices({address})); // Go back to the original value + ASSERT_RESULT(okOrNotSupported, + stream->setDevices({address})); // Go back to the original value } TEST_IO_STREAM(SetDevices, "Check that the stream can be rerouted to SPEAKER or BUILTIN_MIC", @@ -199,7 +191,7 @@ static void checkGetHwAVSync(IDevice* device) { } ASSERT_OK(res); } -TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail", checkGetHwAVSync(device.get())); +TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail", checkGetHwAVSync(getDevice().get())); TEST_P(InputStreamTest, updateSinkMetadata) { doc::test("The HAL should not crash on metadata change"); @@ -259,58 +251,58 @@ TEST_P(OutputStreamTest, updateSourceMetadata) { ASSERT_OK(stream->updateSourceMetadata(initMetadata)); } -TEST_F(AudioPrimaryHidlTest, setMode) { +TEST_P(AudioPrimaryHidlTest, setMode) { doc::test("Make sure setMode always succeeds if mode is valid and fails otherwise"); // Test Invalid values for (int mode : {-2, -1, int(AudioMode::IN_COMMUNICATION) + 1}) { - ASSERT_RESULT(Result::INVALID_ARGUMENTS, device->setMode(AudioMode(mode))) - << "mode=" << mode; + ASSERT_RESULT(Result::INVALID_ARGUMENTS, getDevice()->setMode(AudioMode(mode))) + << "mode=" << mode; } // Test valid values for (AudioMode mode : {AudioMode::IN_CALL, AudioMode::IN_COMMUNICATION, AudioMode::RINGTONE, AudioMode::NORMAL /* Make sure to leave the test in normal mode */}) { - ASSERT_OK(device->setMode(mode)) << "mode=" << toString(mode); + ASSERT_OK(getDevice()->setMode(mode)) << "mode=" << toString(mode); } } -TEST_F(AudioPrimaryHidlTest, setBtHfpSampleRate) { +TEST_P(AudioPrimaryHidlTest, setBtHfpSampleRate) { doc::test( "Make sure setBtHfpSampleRate either succeeds or " "indicates that it is not supported at all, or that the provided value is invalid"); for (auto samplingRate : {8000, 16000, 22050, 24000}) { - ASSERT_RESULT(okOrNotSupportedOrInvalidArgs, device->setBtHfpSampleRate(samplingRate)); + ASSERT_RESULT(okOrNotSupportedOrInvalidArgs, getDevice()->setBtHfpSampleRate(samplingRate)); } } -TEST_F(AudioPrimaryHidlTest, setBtHfpVolume) { +TEST_P(AudioPrimaryHidlTest, setBtHfpVolume) { doc::test( "Make sure setBtHfpVolume is either not supported or " "only succeed if volume is in [0,1]"); - auto ret = device->setBtHfpVolume(0.0); + auto ret = getDevice()->setBtHfpVolume(0.0); ASSERT_TRUE(ret.isOk()); if (ret == Result::NOT_SUPPORTED) { doc::partialTest("setBtHfpVolume is not supported"); return; } - testUnitaryGain([](float volume) { return device->setBtHfpVolume(volume); }); + testUnitaryGain([this](float volume) { return getDevice()->setBtHfpVolume(volume); }); } -TEST_F(AudioPrimaryHidlTest, setBtScoHeadsetDebugName) { +TEST_P(AudioPrimaryHidlTest, setBtScoHeadsetDebugName) { doc::test( "Make sure setBtScoHeadsetDebugName either succeeds or " "indicates that it is not supported"); - ASSERT_RESULT(okOrNotSupported, device->setBtScoHeadsetDebugName("test")); + ASSERT_RESULT(okOrNotSupported, getDevice()->setBtScoHeadsetDebugName("test")); } -TEST_F(AudioPrimaryHidlTest, updateRotation) { +TEST_P(AudioPrimaryHidlTest, updateRotation) { doc::test("Check that the hal can receive the current rotation"); for (Rotation rotation : {Rotation::DEG_0, Rotation::DEG_90, Rotation::DEG_180, Rotation::DEG_270, Rotation::DEG_0}) { - ASSERT_RESULT(okOrNotSupported, device->updateRotation(rotation)); + ASSERT_RESULT(okOrNotSupported, getDevice()->updateRotation(rotation)); } } -TEST_F(BoolAccessorPrimaryHidlTest, setGetBtHfpEnabled) { +TEST_P(BoolAccessorPrimaryHidlTest, setGetBtHfpEnabled) { doc::test("Query and set the BT HFP state"); testAccessors("BtHfpEnabled", Initial{false, OPTIONAL}, {true}, &IPrimaryDevice::setBtHfpEnabled, &IPrimaryDevice::getBtHfpEnabled); diff --git a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h index 8415053ffc..7a52d0e364 100644 --- a/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h +++ b/audio/core/all-versions/vts/functional/4.0/AudioPrimaryHidlHalUtils.h @@ -75,11 +75,18 @@ struct GetSupported { return res; } +#if MAJOR_VERSION <= 5 static Result formats(IStream* stream, hidl_vec& capabilities) { EXPECT_OK(stream->getSupportedFormats(returnIn(capabilities))); - // TODO: this should be an optional function return Result::OK; } +#elif MAJOR_VERSION >= 6 + static Result formats(IStream* stream, hidl_vec& capabilities) { + Result res; + EXPECT_OK(stream->getSupportedFormats(returnIn(res, capabilities))); + return res; + } +#endif }; template diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp index 6314ea72ec..30f8a7ade7 100644 --- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp +++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp @@ -16,3 +16,131 @@ // pull in all the <= 5.0 tests #include "5.0/AudioPrimaryHidlHalTest.cpp" + +const std::vector& getDeviceParametersForFactoryTests() { + static std::vector parameters = [] { + std::vector result; + const auto factories = + ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor); + for (const auto& factoryName : factories) { + result.emplace_back(factoryName, + DeviceManager::getInstance().getPrimary(factoryName) != nullptr + ? DeviceManager::kPrimaryDevice + : ""); + } + return result; + }(); + return parameters; +} + +const std::vector& getDeviceParametersForPrimaryDeviceTests() { + static std::vector parameters = [] { + std::vector result; + const auto primary = std::find_if( + getDeviceParameters().begin(), getDeviceParameters().end(), [](const auto& elem) { + return std::get(elem) == DeviceManager::kPrimaryDevice; + }); + if (primary != getDeviceParameters().end()) result.push_back(*primary); + return result; + }(); + return parameters; +} + +const std::vector& getDeviceParameters() { + static std::vector parameters = [] { + std::vector result; + const auto factories = + ::android::hardware::getAllHalInstanceNames(IDevicesFactory::descriptor); + const auto devices = getCachedPolicyConfig().getModulesWithDevicesNames(); + result.reserve(devices.size()); + for (const auto& factoryName : factories) { + for (const auto& deviceName : devices) { + if (DeviceManager::getInstance().get(factoryName, deviceName) != nullptr) { + result.emplace_back(factoryName, deviceName); + } + } + } + return result; + }(); + return parameters; +} + +const std::vector& getOutputDeviceConfigParameters() { + static std::vector parameters = [] { + std::vector result; + for (const auto& device : getDeviceParameters()) { + auto module = + getCachedPolicyConfig().getModuleFromName(std::get(device)); + for (const auto& ioProfile : module->getOutputProfiles()) { + for (const auto& profile : ioProfile->getAudioProfiles()) { + const auto& channels = profile->getChannels(); + const auto& sampleRates = profile->getSampleRates(); + auto configs = ConfigHelper::combineAudioConfig( + vector(channels.begin(), channels.end()), + vector(sampleRates.begin(), sampleRates.end()), + profile->getFormat()); + auto flags = ioProfile->getFlags(); + for (auto& config : configs) { + // Some combinations of flags declared in the config file require special + // treatment. + bool special = false; + if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { + config.offloadInfo.sampleRateHz = config.sampleRateHz; + config.offloadInfo.channelMask = config.channelMask; + config.offloadInfo.format = config.format; + config.offloadInfo.streamType = AudioStreamType::MUSIC; + config.offloadInfo.bitRatePerSecond = 320; + config.offloadInfo.durationMicroseconds = -1; + config.offloadInfo.bitWidth = 16; + config.offloadInfo.bufferSize = 256; // arbitrary value + config.offloadInfo.usage = AudioUsage::MEDIA; + result.emplace_back( + device, config, + AudioOutputFlag(AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)); + special = true; + } + if ((flags & AUDIO_OUTPUT_FLAG_DIRECT) && + !(flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) { + result.emplace_back(device, config, + AudioOutputFlag(AUDIO_OUTPUT_FLAG_DIRECT)); + special = true; + } + if (flags & AUDIO_OUTPUT_FLAG_PRIMARY) { // ignore the flag + flags &= ~AUDIO_OUTPUT_FLAG_PRIMARY; + } + if (!special) { + result.emplace_back(device, config, AudioOutputFlag(flags)); + } + } + } + } + } + return result; + }(); + return parameters; +} + +const std::vector& getInputDeviceConfigParameters() { + static std::vector parameters = [] { + std::vector result; + for (const auto& device : getDeviceParameters()) { + auto module = + getCachedPolicyConfig().getModuleFromName(std::get(device)); + for (const auto& ioProfile : module->getInputProfiles()) { + for (const auto& profile : ioProfile->getAudioProfiles()) { + const auto& channels = profile->getChannels(); + const auto& sampleRates = profile->getSampleRates(); + auto configs = ConfigHelper::combineAudioConfig( + vector(channels.begin(), channels.end()), + vector(sampleRates.begin(), sampleRates.end()), + profile->getFormat()); + for (const auto& config : configs) { + result.emplace_back(device, config, AudioInputFlag(ioProfile->getFlags())); + } + } + } + } + return result; + }(); + return parameters; +} diff --git a/audio/core/all-versions/vts/functional/6.0/EnvironmentTearDown.h b/audio/core/all-versions/vts/functional/6.0/EnvironmentTearDown.h new file mode 100644 index 0000000000..593759f17c --- /dev/null +++ b/audio/core/all-versions/vts/functional/6.0/EnvironmentTearDown.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2019 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. + */ + +#ifndef ANDROID_HARDWARE_AUDIO_CORE_6_0_ENVIRONMENT_TEARDOWN_H +#define ANDROID_HARDWARE_AUDIO_CORE_6_0_ENVIRONMENT_TEARDOWN_H + +#include + +#include "utility/EnvironmentTearDown.h" + +class Environment : public ::android::hardware::audio::common::test::utility::EnvironmentTearDown, + public ::testing::Environment { + public: + void init(int* /*argc*/, char** /*argv*/) {} // emulate VtsHalHidlTargetTestEnvBase + private: + void TearDown() override { executeAllTearDowns(); } +}; + +// FIXME: Will be removed while making getDeviceParameters to use the config +static constexpr const char* kDefaultServiceName = "default"; + +#endif // ANDROID_HARDWARE_AUDIO_CORE_6_0_ENVIRONMENT_TEARDOWN_H diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h index 6c51c1ba7f..468f9b2da6 100644 --- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h +++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h @@ -23,7 +23,10 @@ #include #include #include +#include +#include #include +#include #include #include @@ -31,7 +34,9 @@ #include +#if MAJOR_VERSION <= 5 #include +#endif #include @@ -44,16 +49,25 @@ #include #include #include +#if MAJOR_VERSION >= 6 +#include +#include +#endif #include #include "utility/AssertOk.h" #include "utility/Documentation.h" -#include "utility/EnvironmentTearDown.h" #include "utility/PrettyPrintAudioTypes.h" #include "utility/ReturnIn.h" #include "utility/ValidateXml.h" +#if MAJOR_VERSION <= 5 +#include "2.0/EnvironmentTearDown.h" +#elif MAJOR_VERSION >= 6 +#include "6.0/EnvironmentTearDown.h" +#endif + /** Provide version specific functions that are used in the generic tests */ #if MAJOR_VERSION == 2 #include "2.0/AudioPrimaryHidlHalUtils.h" @@ -84,7 +98,9 @@ using ::android::hardware::kSynchronizedReadWrite; using ::android::hardware::MessageQueue; using ::android::hardware::MQDescriptorSync; using ::android::hardware::Return; +using ::android::hardware::audio::common::utils::EnumBitfield; using ::android::hardware::audio::common::utils::mkEnumBitfield; +using ::android::hardware::details::toHexString; using namespace ::android::hardware::audio::common::CPP_VERSION; using namespace ::android::hardware::audio::common::test::utility; @@ -105,14 +121,43 @@ static auto invalidStateOrNotSupported = {Result::INVALID_STATE, Result::NOT_SUP class AudioHidlTestEnvironment : public ::Environment { public: - virtual void registerTestServices() override { registerTestService(); } +#if MAJOR_VERSION <= 5 + void registerTestServices() override { registerTestService(); } +#endif }; // Instance to register global tearDown static AudioHidlTestEnvironment* environment; -class HidlTest : public ::testing::VtsHalHidlTargetTestBase { - protected: +#define AUDIO_PRIMARY_HIDL_HAL_TEST +#include "DeviceManager.h" + +#if MAJOR_VERSION <= 5 +using HidlTestBase = ::testing::VtsHalHidlTargetTestBase; +#elif MAJOR_VERSION >= 6 +using HidlTestBase = ::testing::Test; +#endif + +class HidlTest : public HidlTestBase { + public: + virtual ~HidlTest() = default; + + protected: + // Factory and device name getters to be overridden in subclasses. + virtual const std::string& getFactoryName() const = 0; + virtual const std::string& getDeviceName() const = 0; + + sp getDevicesFactory() const { + return DevicesFactoryManager::getInstance().get(getFactoryName()); + } + sp getDevice() const { + return DeviceManager::getInstance().get(getFactoryName(), getDeviceName()); + } + bool resetDevice() const { + return DeviceManager::getInstance().reset(getFactoryName(), getDeviceName()); + } + bool areAudioPatchesSupported() { return extract(getDevice()->supportsAudioPatches()); } + // Convenient member to store results Result res; }; @@ -158,7 +203,25 @@ class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig { } mStatus = android::deserializeAudioPolicyFile(mFilePath.c_str(), this); if (mStatus == OK) { - mPrimaryModule = getHwModules().getModuleFromName("primary"); + mPrimaryModule = getHwModules().getModuleFromName(DeviceManager::kPrimaryDevice); + // Available devices are not 'attached' to modules at this moment. + // Need to go over available devices and find their module. + for (const auto& device : availableOutputDevices) { + for (const auto& module : hwModules) { + if (module->getDeclaredDevices().indexOf(device) >= 0) { + mModulesWithDevicesNames.insert(module->getName()); + break; + } + } + } + for (const auto& device : availableInputDevices) { + for (const auto& module : hwModules) { + if (module->getDeclaredDevices().indexOf(device) >= 0) { + mModulesWithDevicesNames.insert(module->getName()); + break; + } + } + } } } status_t getStatus() const { return mStatus; } @@ -171,12 +234,19 @@ class PolicyConfig : private PolicyConfigData, public AudioPolicyConfig { } } const std::string& getFilePath() const { return mFilePath; } + sp getModuleFromName(const std::string& name) const { + return getHwModules().getModuleFromName(name.c_str()); + } sp getPrimaryModule() const { return mPrimaryModule; } + const std::set& getModulesWithDevicesNames() const { + return mModulesWithDevicesNames; + } private: status_t mStatus = NO_INIT; std::string mFilePath; sp mPrimaryModule = nullptr; + std::set mModulesWithDevicesNames; }; // Cached policy config after parsing for faster test startup @@ -189,61 +259,113 @@ const PolicyConfig& getCachedPolicyConfig() { return *policyConfig; } -class AudioPolicyConfigTest : public HidlTest { - public: +class AudioPolicyConfigTest : public HidlTestBase { + public: void SetUp() override { - ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp()); // setup base - + ASSERT_NO_FATAL_FAILURE(HidlTestBase::SetUp()); // setup base auto& policyConfig = getCachedPolicyConfig(); ASSERT_EQ(0, policyConfig.getStatus()) << policyConfig.getError(); - - mPrimaryConfig = policyConfig.getPrimaryModule(); - ASSERT_TRUE(mPrimaryConfig) << "Could not find primary module in configuration file: " - << policyConfig.getFilePath(); } - sp mPrimaryConfig = nullptr; }; TEST_F(AudioPolicyConfigTest, LoadAudioPolicyXMLConfiguration) { doc::test("Test parsing audio_policy_configuration.xml (called in SetUp)"); } +TEST_F(AudioPolicyConfigTest, HasPrimaryModule) { + auto& policyConfig = getCachedPolicyConfig(); + ASSERT_TRUE(policyConfig.getPrimaryModule() != nullptr) + << "Could not find primary module in configuration file: " + << policyConfig.getFilePath(); +} + +////////////////////////////////////////////////////////////////////////////// +//////////////////// Test parameter types and definitions //////////////////// +////////////////////////////////////////////////////////////////////////////// + +enum { PARAM_FACTORY_NAME, PARAM_DEVICE_NAME }; +using DeviceParameter = std::tuple; + +static inline std::string DeviceParameterToString( + const ::testing::TestParamInfo& info) { + const auto& deviceName = std::get(info.param); +#if MAJOR_VERSION <= 5 + return !deviceName.empty() ? deviceName : std::to_string(info.index); +#elif MAJOR_VERSION >= 6 + const auto factoryName = + ::android::hardware::PrintInstanceNameToString(::testing::TestParamInfo{ + std::get(info.param), info.index}); + return !deviceName.empty() ? factoryName + "_" + deviceName : factoryName; +#endif +} + +#if MAJOR_VERSION <= 5 +// For V2..5 the factory is looked up using the instance name passed +// in the environment, only one factory is returned. This is because the VTS +// framework will call the test for each instance. Only the primary device of +// the default service factory can be tested. + +// Return a pair of <"default", "primary"> or <[non-default name], ""> +// This is used to parametrize device factory tests. +// The device name is used to indicate whether IPrimaryDevice is required. +const std::vector& getDeviceParametersForFactoryTests() { + static std::vector parameters = { + {environment->getServiceName(), + environment->getServiceName() == kDefaultServiceName + ? DeviceManager::kPrimaryDevice + : ""}}; + return parameters; +} +// Return a pair of <"default", "primary"> or nothing. +// This is used to parametrize primary device tests. +const std::vector& getDeviceParametersForPrimaryDeviceTests() { + static std::vector parameters = + !std::get(*getDeviceParametersForFactoryTests().begin()).empty() + ? getDeviceParametersForFactoryTests() + : std::vector{}; + return parameters; +} +// In V2..5 device tests must only test the primary device. +// No device tests are executed for non-primary devices. +const std::vector& getDeviceParameters() { + return getDeviceParametersForPrimaryDeviceTests(); +} +#elif MAJOR_VERSION >= 6 +// For V6 and above these functions are implemented in 6.0/AudioPrimaryHidlHalTest.cpp +const std::vector& getDeviceParametersForFactoryTests(); +const std::vector& getDeviceParametersForPrimaryDeviceTests(); +const std::vector& getDeviceParameters(); +#endif + +class AudioHidlTestWithDeviceParameter : public HidlTest, + public ::testing::WithParamInterface { + protected: + const std::string& getFactoryName() const override { + return std::get(GetParam()); + } + const std::string& getDeviceName() const override { + return std::get(GetParam()); + } +}; + ////////////////////////////////////////////////////////////////////////////// ////////////////////// getService audio_devices_factory ////////////////////// ////////////////////////////////////////////////////////////////////////////// -// Test all audio devices -class AudioHidlTest : public AudioPolicyConfigTest { - public: - static void SetUpTestSuite() { - devicesFactory = ::testing::VtsHalHidlTargetTestBase::getService( - environment->getServiceName()); - } - - static void TearDownTestSuite() { devicesFactory.clear(); } - - void SetUp() override { - ASSERT_NO_FATAL_FAILURE(AudioPolicyConfigTest::SetUp()); // setup base - // Failures during SetUpTestSuite do not cause test termination. - ASSERT_TRUE(devicesFactory != nullptr); - } - - protected: - // Cache the devicesFactory retrieval to speed up each test by ~0.5s - static sp devicesFactory; - - static bool isPrimaryDeviceOptional() { - // It's OK not to have "primary" device on non-default audio HAL service. - return environment->getServiceName() != kDefaultServiceName; +// Test audio devices factory +class AudioHidlTest : public AudioHidlTestWithDeviceParameter { + public: + void SetUp() override { + ASSERT_NO_FATAL_FAILURE(AudioHidlTestWithDeviceParameter::SetUp()); // setup base + ASSERT_TRUE(getDevicesFactory() != nullptr); } }; -sp AudioHidlTest::devicesFactory; -TEST_F(AudioHidlTest, GetAudioDevicesFactoryService) { +TEST_P(AudioHidlTest, GetAudioDevicesFactoryService) { doc::test("Test the getService"); } -TEST_F(AudioHidlTest, OpenDeviceInvalidParameter) { +TEST_P(AudioHidlTest, OpenDeviceInvalidParameter) { doc::test("Test passing an invalid parameter to openDevice"); Result result; sp device; @@ -252,82 +374,80 @@ TEST_F(AudioHidlTest, OpenDeviceInvalidParameter) { #elif MAJOR_VERSION >= 4 auto invalidDevice = "Non existing device"; #endif - ASSERT_OK(devicesFactory->openDevice(invalidDevice, returnIn(result, device))); + ASSERT_OK(getDevicesFactory()->openDevice(invalidDevice, returnIn(result, device))); ASSERT_EQ(Result::INVALID_ARGUMENTS, result); ASSERT_TRUE(device == nullptr); } +INSTANTIATE_TEST_CASE_P(AudioHidl, AudioHidlTest, + ::testing::ValuesIn(getDeviceParametersForFactoryTests()), + &DeviceParameterToString); + +////////////////////////////////////////////////////////////////////////////// +/////////////////////////////// openDevice /////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +// Test all audio devices +class AudioHidlDeviceTest : public AudioHidlTest { + public: + void SetUp() override { + ASSERT_NO_FATAL_FAILURE(AudioHidlTest::SetUp()); // setup base + ASSERT_TRUE(getDevice() != nullptr); + } +}; + +TEST_P(AudioHidlDeviceTest, OpenDevice) { + doc::test("Test openDevice (called during setup)"); +} + +TEST_P(AudioHidlDeviceTest, Init) { + doc::test("Test that the audio hal initialized correctly"); + ASSERT_OK(getDevice()->initCheck()); +} + +INSTANTIATE_TEST_CASE_P(AudioHidlDevice, AudioHidlDeviceTest, + ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString); + ////////////////////////////////////////////////////////////////////////////// /////////////////////////////// openDevice primary /////////////////////////// ////////////////////////////////////////////////////////////////////////////// // Test the primary device -class AudioPrimaryHidlTest : public AudioHidlTest { - public: - static void SetUpTestSuite() { - ASSERT_NO_FATAL_FAILURE(AudioHidlTest::SetUpTestSuite()); - ASSERT_NO_FATAL_FAILURE(initPrimaryDevice()); - } - - static void TearDownTestSuite() { - device.clear(); - AudioHidlTest::TearDownTestSuite(); - } - +class AudioPrimaryHidlTest : public AudioHidlDeviceTest { + public: void SetUp() override { - ASSERT_NO_FATAL_FAILURE(AudioHidlTest::SetUp()); // setup base - if (device == nullptr && isPrimaryDeviceOptional()) { - GTEST_SKIP() << "No primary device on this factory"; - } - ASSERT_TRUE(device != nullptr); + ASSERT_NO_FATAL_FAILURE(AudioHidlDeviceTest::SetUp()); // setup base + ASSERT_TRUE(getDevice() != nullptr); } - protected: - // Cache the device opening to speed up each test by ~0.5s - static sp device; - - static void initPrimaryDevice() { - // Failures during test suite set up do not cause test termination. - ASSERT_TRUE(devicesFactory != nullptr); - Result result; -#if MAJOR_VERSION == 2 - sp baseDevice; - ASSERT_OK(devicesFactory->openDevice(IDevicesFactory::Device::PRIMARY, - returnIn(result, baseDevice))); - ASSERT_OK(result); - ASSERT_TRUE(baseDevice != nullptr); - - device = IPrimaryDevice::castFrom(baseDevice); -#elif MAJOR_VERSION >= 4 - ASSERT_OK(devicesFactory->openPrimaryDevice(returnIn(result, device))); - ASSERT_OK(result); -#endif + protected: + sp getDevice() const { + return DeviceManager::getInstance().getPrimary(getFactoryName()); } }; -sp AudioPrimaryHidlTest::device; -TEST_F(AudioPrimaryHidlTest, OpenPrimaryDevice) { - doc::test("Test the openDevice (called during setup)"); +TEST_P(AudioPrimaryHidlTest, OpenPrimaryDevice) { + doc::test("Test openPrimaryDevice (called during setup)"); } -TEST_F(AudioPrimaryHidlTest, Init) { - doc::test("Test that the audio primary hal initialized correctly"); - ASSERT_OK(device->initCheck()); -} +INSTANTIATE_TEST_CASE_P(AudioPrimaryHidl, AudioPrimaryHidlTest, + ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()), + &DeviceParameterToString); ////////////////////////////////////////////////////////////////////////////// ///////////////////// {set,get}{Master,Mic}{Mute,Volume} ///////////////////// ////////////////////////////////////////////////////////////////////////////// -template -class AccessorPrimaryHidlTest : public AudioPrimaryHidlTest { - protected: +template +class AccessorHidlTest : public BaseTestClass { + protected: enum Optionality { REQUIRED, OPTIONAL }; struct Initial { // Initial property value Initial(Property value, Optionality check = REQUIRED) : value(value), check(check) {} Property value; Optionality check; // If this initial value should be checked }; + using BaseTestClass::res; /** Test a property getter and setter. * The getter and/or the setter may return NOT_SUPPORTED if optionality == OPTIONAL. */ @@ -339,7 +459,7 @@ class AccessorPrimaryHidlTest : public AudioPrimaryHidlTest { optionality == OPTIONAL ? Result::NOT_SUPPORTED : Result::OK}; Property initialValue = expectedInitial.value; - ASSERT_OK((device.get()->*getter)(returnIn(res, initialValue))); + ASSERT_OK((BaseTestClass::getDevice().get()->*getter)(returnIn(res, initialValue))); ASSERT_RESULT(expectedResults, res); if (res == Result::OK && expectedInitial.check == REQUIRED) { EXPECT_EQ(expectedInitial.value, initialValue); @@ -350,7 +470,7 @@ class AccessorPrimaryHidlTest : public AudioPrimaryHidlTest { for (Property setValue : valuesToTest) { SCOPED_TRACE("Test " + propertyName + " getter and setter for " + testing::PrintToString(setValue)); - auto ret = (device.get()->*setter)(setValue); + auto ret = (BaseTestClass::getDevice().get()->*setter)(setValue); ASSERT_RESULT(expectedResults, ret); if (ret == Result::NOT_SUPPORTED) { doc::partialTest(propertyName + " setter is not supported"); @@ -358,7 +478,7 @@ class AccessorPrimaryHidlTest : public AudioPrimaryHidlTest { } Property getValue; // Make sure the getter returns the same value just set - ASSERT_OK((device.get()->*getter)(returnIn(res, getValue))); + ASSERT_OK((BaseTestClass::getDevice().get()->*getter)(returnIn(res, getValue))); ASSERT_RESULT(expectedResults, res); if (res == Result::NOT_SUPPORTED) { doc::partialTest(propertyName + " getter is not supported"); @@ -370,31 +490,40 @@ class AccessorPrimaryHidlTest : public AudioPrimaryHidlTest { for (Property invalidValue : invalidValues) { SCOPED_TRACE("Try to set " + propertyName + " with the invalid value " + testing::PrintToString(invalidValue)); - EXPECT_RESULT(invalidArgsOrNotSupported, (device.get()->*setter)(invalidValue)); + EXPECT_RESULT(invalidArgsOrNotSupported, + (BaseTestClass::getDevice().get()->*setter)(invalidValue)); } // Restore initial value - EXPECT_RESULT(expectedResults, (device.get()->*setter)(initialValue)); + EXPECT_RESULT(expectedResults, (BaseTestClass::getDevice().get()->*setter)(initialValue)); } }; -using BoolAccessorPrimaryHidlTest = AccessorPrimaryHidlTest; +using BoolAccessorHidlTest = AccessorHidlTest; +using BoolAccessorPrimaryHidlTest = AccessorHidlTest; -TEST_F(BoolAccessorPrimaryHidlTest, MicMuteTest) { +TEST_P(BoolAccessorHidlTest, MicMuteTest) { doc::test("Check that the mic can be muted and unmuted"); - testAccessors("mic mute", Initial{false}, {true}, &IDevice::setMicMute, &IDevice::getMicMute); + testAccessors("mic mute", Initial{false}, {true}, &IDevice::setMicMute, + &IDevice::getMicMute); // TODO: check that the mic is really muted (all sample are 0) } -TEST_F(BoolAccessorPrimaryHidlTest, MasterMuteTest) { +TEST_P(BoolAccessorHidlTest, MasterMuteTest) { doc::test("If master mute is supported, try to mute and unmute the master output"); testAccessors("master mute", Initial{false}, {true}, &IDevice::setMasterMute, &IDevice::getMasterMute); // TODO: check that the master volume is really muted } -using FloatAccessorPrimaryHidlTest = AccessorPrimaryHidlTest; -TEST_F(FloatAccessorPrimaryHidlTest, MasterVolumeTest) { +INSTANTIATE_TEST_CASE_P(BoolAccessorHidl, BoolAccessorHidlTest, + ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString); +INSTANTIATE_TEST_CASE_P(BoolAccessorPrimaryHidl, BoolAccessorPrimaryHidlTest, + ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()), + &DeviceParameterToString); + +using FloatAccessorHidlTest = AccessorHidlTest; +TEST_P(FloatAccessorHidlTest, MasterVolumeTest) { doc::test("Test the master volume if supported"); testAccessors( "master volume", Initial{1}, {0, 0.5}, &IDevice::setMasterVolume, &IDevice::getMasterVolume, @@ -402,121 +531,135 @@ TEST_F(FloatAccessorPrimaryHidlTest, MasterVolumeTest) { // TODO: check that the master volume is really changed } +INSTANTIATE_TEST_CASE_P(FloatAccessorHidl, FloatAccessorHidlTest, + ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString); + ////////////////////////////////////////////////////////////////////////////// //////////////////////////////// AudioPatches //////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -class AudioPatchPrimaryHidlTest : public AudioPrimaryHidlTest { - protected: - bool areAudioPatchesSupported() { return extract(device->supportsAudioPatches()); } +class AudioPatchHidlTest : public AudioHidlDeviceTest { + public: + void SetUp() override { + ASSERT_NO_FATAL_FAILURE(AudioHidlDeviceTest::SetUp()); // setup base + if (!areAudioPatchesSupported()) { + GTEST_SKIP() << "Audio patches are not supported"; + } + } }; -TEST_F(AudioPatchPrimaryHidlTest, AudioPatches) { +TEST_P(AudioPatchHidlTest, AudioPatches) { doc::test("Test if audio patches are supported"); - if (!areAudioPatchesSupported()) { - doc::partialTest("Audio patches are not supported"); - return; - } // TODO: test audio patches } -////////////////////////////////////////////////////////////////////////////// -//////////////// Required and recommended audio format support /////////////// -// From: -// https://source.android.com/compatibility/android-cdd.html#5_4_audio_recording -// From: -// https://source.android.com/compatibility/android-cdd.html#5_5_audio_playback -/////////// TODO: move to the beginning of the file for easier update //////// -////////////////////////////////////////////////////////////////////////////// +INSTANTIATE_TEST_CASE_P(AudioPatchHidl, AudioPatchHidlTest, + ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString); -class AudioConfigPrimaryTest : public AudioPatchPrimaryHidlTest { - public: - // for retro compatibility only test the primary device IN_BUILTIN_MIC - // FIXME: in the next audio HAL version, test all available devices - static bool primaryHasMic() { - auto& policyConfig = getCachedPolicyConfig(); - if (policyConfig.getStatus() != OK || policyConfig.getPrimaryModule() == nullptr) { - return true; // Could not get the information, run all tests - } - auto getMic = [](auto& devs) { return devs.getDevice( - AUDIO_DEVICE_IN_BUILTIN_MIC, {}, AUDIO_FORMAT_DEFAULT); }; - auto primaryMic = getMic(policyConfig.getPrimaryModule()->getDeclaredDevices()); - auto availableMic = getMic(policyConfig.getAvailableInputDevices()); +// Nesting a tuple in another tuple allows to use GTest Combine function to generate +// all combinations of devices and configs. +enum { PARAM_DEVICE, PARAM_CONFIG, PARAM_FLAGS }; +enum { INDEX_INPUT, INDEX_OUTPUT }; +using DeviceConfigParameter = + std::tuple>; - return primaryMic != nullptr && primaryMic->equals(availableMic); - } +#if MAJOR_VERSION >= 6 +const std::vector& getInputDeviceConfigParameters(); +const std::vector& getOutputDeviceConfigParameters(); +#endif - // Cache result ? - static const vector getRequiredSupportPlaybackAudioConfig() { - return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, - {8000, 11025, 16000, 22050, 32000, 44100}, - {AudioFormat::PCM_16_BIT}); +#if MAJOR_VERSION >= 4 +static string SanitizeStringForGTestName(const string& s) { + string result = s; + for (size_t i = 0; i < result.size(); i++) { + // gtest test names must only contain alphanumeric characters + if (!std::isalnum(result[i])) result[i] = '_'; } - - static const vector getRecommendedSupportPlaybackAudioConfig() { - return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, - {24000, 48000}, {AudioFormat::PCM_16_BIT}); - } - - static const vector getSupportedPlaybackAudioConfig() { - // TODO: retrieve audio config supported by the platform - // as declared in the policy configuration - return {}; - } - - static const vector getRequiredSupportCaptureAudioConfig() { - if (!primaryHasMic()) return {}; - return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100}, - {AudioFormat::PCM_16_BIT}); - } - static const vector getRecommendedSupportCaptureAudioConfig() { - if (!primaryHasMic()) return {}; - return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000}, - {AudioFormat::PCM_16_BIT}); - } - static const vector getSupportedCaptureAudioConfig() { - // TODO: retrieve audio config supported by the platform - // as declared in the policy configuration - return {}; - } - - private: - static const vector combineAudioConfig(vector channelMasks, - vector sampleRates, - vector formats) { - vector configs; - for (auto channelMask : channelMasks) { - for (auto sampleRate : sampleRates) { - for (auto format : formats) { - AudioConfig config{}; - // leave offloadInfo to 0 - config.channelMask = mkEnumBitfield(channelMask); - config.sampleRateHz = sampleRate; - config.format = format; - // FIXME: leave frameCount to 0 ? - configs.push_back(config); - } - } - } - return configs; - } -}; + return result; +} +#endif /** Generate a test name based on an audio config. * * As the only parameter changing are channel mask and sample rate, * only print those ones in the test name. */ -static string generateTestName(const testing::TestParamInfo& info) { - const AudioConfig& config = info.param; - return to_string(info.index) + "__" + to_string(config.sampleRateHz) + "_" + +static string DeviceConfigParameterToString( + const testing::TestParamInfo& info) { + const AudioConfig& config = std::get(info.param); + const auto deviceName = DeviceParameterToString(::testing::TestParamInfo{ + std::get(info.param), info.index}); + return (deviceName.empty() ? "" : deviceName + "_") + to_string(info.index) + "__" + + to_string(config.sampleRateHz) + "_" + // "MONO" is more clear than "FRONT_LEFT" ((config.channelMask == mkEnumBitfield(AudioChannelMask::OUT_MONO) || config.channelMask == mkEnumBitfield(AudioChannelMask::IN_MONO)) - ? "MONO" - : ::testing::PrintToString(config.channelMask)); + ? "MONO" +#if MAJOR_VERSION == 2 + : ::testing::PrintToString(config.channelMask) +#elif MAJOR_VERSION >= 4 + // In V4 and above the channel mask is a bitfield. + // Printing its value using HIDL's toString for a bitfield emits a lot of extra + // text due to overlapping constant values. Instead, we print the bitfield value + // as if it was a single value + its hex representation + : SanitizeStringForGTestName( + ::testing::PrintToString(AudioChannelMask(config.channelMask)) + "_" + + toHexString(config.channelMask)) +#endif + ) + + "_" + +#if MAJOR_VERSION == 2 + std::visit([](auto&& arg) -> std::string { return ::testing::PrintToString(arg); }, + std::get(info.param)); +#elif MAJOR_VERSION >= 4 + SanitizeStringForGTestName(std::visit( + [](auto&& arg) -> std::string { + using T = std::decay_t; + // Need to use FQN of toString to avoid confusing the compiler + return ::android::hardware::audio::common::CPP_VERSION::toString( + hidl_bitfield(arg)); + }, + std::get(info.param))); +#endif } +class AudioHidlTestWithDeviceConfigParameter + : public HidlTest, + public ::testing::WithParamInterface { + protected: + void SetUp() override { + ASSERT_NO_FATAL_FAILURE(HidlTest::SetUp()); // setup base + ASSERT_TRUE(getDevicesFactory() != nullptr); + ASSERT_TRUE(getDevice() != nullptr); + } + const std::string& getFactoryName() const override { + return std::get(std::get(GetParam())); + } + const std::string& getDeviceName() const override { + return std::get(std::get(GetParam())); + } + const AudioConfig& getConfig() const { return std::get(GetParam()); } +#if MAJOR_VERSION == 2 + AudioInputFlag getInputFlags() const { + return std::get(std::get(GetParam())); + } + AudioOutputFlag getOutputFlags() const { + return std::get(std::get(GetParam())); + } +#elif MAJOR_VERSION >= 4 + hidl_bitfield getInputFlags() const { + return hidl_bitfield( + std::get(std::get(GetParam()))); + } + hidl_bitfield getOutputFlags() const { + return hidl_bitfield( + std::get(std::get(GetParam()))); + } +#endif +}; + +#include "ConfigHelper.h" + ////////////////////////////////////////////////////////////////////////////// ///////////////////////////// getInputBufferSize ///////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -525,12 +668,11 @@ static string generateTestName(const testing::TestParamInfo& info) // android.hardware.microphone // how to get this value ? is it a property ??? -class AudioCaptureConfigPrimaryTest : public AudioConfigPrimaryTest, - public ::testing::WithParamInterface { - protected: +class AudioCaptureConfigTest : public AudioHidlTestWithDeviceConfigParameter { + protected: void inputBufferSizeTest(const AudioConfig& audioConfig, bool supportRequired) { uint64_t bufferSize; - ASSERT_OK(device->getInputBufferSize(audioConfig, returnIn(res, bufferSize))); + ASSERT_OK(getDevice()->getInputBufferSize(audioConfig, returnIn(res, bufferSize))); switch (res) { case Result::INVALID_ARGUMENTS: @@ -549,44 +691,60 @@ class AudioCaptureConfigPrimaryTest : public AudioConfigPrimaryTest, // Test that the required capture config and those declared in the policy are // indeed supported -class RequiredInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {}; +class RequiredInputBufferSizeTest : public AudioCaptureConfigTest {}; TEST_P(RequiredInputBufferSizeTest, RequiredInputBufferSizeTest) { doc::test( "Input buffer size must be retrievable for a format with required " "support."); - inputBufferSizeTest(GetParam(), true); + inputBufferSizeTest(getConfig(), true); } -INSTANTIATE_TEST_CASE_P( - RequiredInputBufferSize, RequiredInputBufferSizeTest, - ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()), - &generateTestName); -INSTANTIATE_TEST_CASE_P( - SupportedInputBufferSize, RequiredInputBufferSizeTest, - ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()), - &generateTestName); // Test that the recommended capture config are supported or lead to a // INVALID_ARGUMENTS return -class OptionalInputBufferSizeTest : public AudioCaptureConfigPrimaryTest {}; +class OptionalInputBufferSizeTest : public AudioCaptureConfigTest {}; TEST_P(OptionalInputBufferSizeTest, OptionalInputBufferSizeTest) { doc::test( - "Input buffer size should be retrievable for a format with recommended " - "support."); - inputBufferSizeTest(GetParam(), false); + "Input buffer size should be retrievable for a format with recommended " + "support."); + inputBufferSizeTest(getConfig(), false); } + +#if MAJOR_VERSION <= 5 +// For V2..5 test the primary device according to CDD requirements. INSTANTIATE_TEST_CASE_P( - RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest, - ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()), - &generateTestName); + RequiredInputBufferSize, RequiredInputBufferSizeTest, + ::testing::Combine( + ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()), + ::testing::ValuesIn(ConfigHelper::getRequiredSupportCaptureAudioConfig()), + ::testing::Values(AudioInputFlag::NONE)), + &DeviceConfigParameterToString); +INSTANTIATE_TEST_CASE_P( + SupportedInputBufferSize, RequiredInputBufferSizeTest, + ::testing::Combine(::testing::ValuesIn(getDeviceParameters()), + ::testing::ValuesIn(ConfigHelper::getSupportedCaptureAudioConfig()), + ::testing::Values(AudioInputFlag::NONE)), + &DeviceConfigParameterToString); +INSTANTIATE_TEST_CASE_P( + RecommendedCaptureAudioConfigSupport, OptionalInputBufferSizeTest, + ::testing::Combine( + ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()), + ::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig()), + ::testing::Values(AudioInputFlag::NONE)), + &DeviceConfigParameterToString); +#elif MAJOR_VERSION >= 6 +INSTANTIATE_TEST_CASE_P(SupportedInputBufferSize, RequiredInputBufferSizeTest, + ::testing::ValuesIn(getInputDeviceConfigParameters()), + &DeviceConfigParameterToString); +#endif ////////////////////////////////////////////////////////////////////////////// /////////////////////////////// setScreenState /////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -TEST_F(AudioPrimaryHidlTest, setScreenState) { +TEST_P(AudioHidlDeviceTest, setScreenState) { doc::test("Check that the hal can receive the screen state"); for (bool turnedOn : {false, true, true, false, false}) { - ASSERT_RESULT(okOrNotSupported, device->setScreenState(turnedOn)); + ASSERT_RESULT(okOrNotSupported, getDevice()->setScreenState(turnedOn)); } } @@ -594,15 +752,16 @@ TEST_F(AudioPrimaryHidlTest, setScreenState) { //////////////////////////// {get,set}Parameters ///////////////////////////// ////////////////////////////////////////////////////////////////////////////// -TEST_F(AudioPrimaryHidlTest, getParameters) { +TEST_P(AudioHidlDeviceTest, getParameters) { doc::test("Check that the hal can set and get parameters"); hidl_vec context; hidl_vec keys; hidl_vec values; - ASSERT_OK(Parameters::get(device, keys, returnIn(res, values))); - ASSERT_OK(Parameters::set(device, values)); + ASSERT_OK(Parameters::get(getDevice(), keys, returnIn(res, values))); + ASSERT_RESULT(okOrNotSupported, res); + ASSERT_RESULT(okOrNotSupported, Parameters::set(getDevice(), values)); values.resize(0); - ASSERT_OK(Parameters::set(device, values)); + ASSERT_RESULT(okOrNotSupported, Parameters::set(getDevice(), values)); } ////////////////////////////////////////////////////////////////////////////// @@ -643,14 +802,14 @@ static void testDebugDump(DebugDump debugDump) { EXPECT_EQ(0, close(fds[1])) << errno; } -TEST_F(AudioPrimaryHidlTest, DebugDump) { +TEST_P(AudioHidlDeviceTest, DebugDump) { doc::test("Check that the hal can dump its state without error"); - testDebugDump([](const auto& handle) { return dump(device, handle); }); + testDebugDump([this](const auto& handle) { return dump(getDevice(), handle); }); } -TEST_F(AudioPrimaryHidlTest, DebugDumpInvalidArguments) { +TEST_P(AudioHidlDeviceTest, DebugDumpInvalidArguments) { doc::test("Check that the hal dump doesn't crash on invalid arguments"); - ASSERT_OK(dump(device, hidl_handle())); + ASSERT_OK(dump(getDevice(), hidl_handle())); } ////////////////////////////////////////////////////////////////////////////// @@ -658,9 +817,8 @@ TEST_F(AudioPrimaryHidlTest, DebugDumpInvalidArguments) { ////////////////////////////////////////////////////////////////////////////// template -class OpenStreamTest : public AudioConfigPrimaryTest, - public ::testing::WithParamInterface { - protected: +class OpenStreamTest : public AudioHidlTestWithDeviceConfigParameter { + protected: template void testOpen(Open openStream, const AudioConfig& config) { // FIXME: Open a stream without an IOHandle @@ -701,7 +859,7 @@ class OpenStreamTest : public AudioConfigPrimaryTest, return res; } - void waitForStreamDestruction() { + static void waitForStreamDestruction() { // FIXME: there is no way to know when the remote IStream is being destroyed // Binder does not support testing if an object is alive, thus // wait for 100ms to let the binder destruction propagates and @@ -712,12 +870,12 @@ class OpenStreamTest : public AudioConfigPrimaryTest, usleep(100 * 1000); } - private: + private: void TearDown() override { if (open) { ASSERT_OK(closeStream()); } - AudioConfigPrimaryTest::TearDown(); + AudioHidlTestWithDeviceConfigParameter::TearDown(); } protected: @@ -732,20 +890,19 @@ class OpenStreamTest : public AudioConfigPrimaryTest, class OutputStreamTest : public OpenStreamTest { void SetUp() override { ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base - if (IsSkipped()) return; // do not attempt to use 'device' address.device = AudioDevice::OUT_DEFAULT; - const AudioConfig& config = GetParam(); - // TODO: test all flag combination - auto flags = mkEnumBitfield(AudioOutputFlag::NONE); + const AudioConfig& config = getConfig(); + auto flags = getOutputFlags(); testOpen( - [&](AudioIoHandle handle, AudioConfig config, auto cb) { + [&](AudioIoHandle handle, AudioConfig config, auto cb) { #if MAJOR_VERSION == 2 - return device->openOutputStream(handle, address, config, flags, cb); + return getDevice()->openOutputStream(handle, address, config, flags, cb); #elif MAJOR_VERSION >= 4 - return device->openOutputStream(handle, address, config, flags, initMetadata, cb); + return getDevice()->openOutputStream(handle, address, config, flags, + initMetadata, cb); #endif - }, - config); + }, + config); } #if MAJOR_VERSION >= 4 @@ -762,35 +919,52 @@ TEST_P(OutputStreamTest, OpenOutputStreamTest) { "recommended config"); // Open done in SetUp } -INSTANTIATE_TEST_CASE_P( - RequiredOutputStreamConfigSupport, OutputStreamTest, - ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportPlaybackAudioConfig()), - &generateTestName); -INSTANTIATE_TEST_CASE_P( - SupportedOutputStreamConfig, OutputStreamTest, - ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedPlaybackAudioConfig()), - &generateTestName); +#if MAJOR_VERSION <= 5 +// For V2..5 test the primary device according to CDD requirements. INSTANTIATE_TEST_CASE_P( - RecommendedOutputStreamConfigSupport, OutputStreamTest, - ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportPlaybackAudioConfig()), - &generateTestName); + RequiredOutputStreamConfigSupport, OutputStreamTest, + ::testing::Combine( + ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()), + ::testing::ValuesIn(ConfigHelper::getRequiredSupportPlaybackAudioConfig()), + ::testing::Values(AudioOutputFlag::NONE)), + &DeviceConfigParameterToString); +INSTANTIATE_TEST_CASE_P( + SupportedOutputStreamConfig, OutputStreamTest, + ::testing::Combine(::testing::ValuesIn(getDeviceParameters()), + ::testing::ValuesIn(ConfigHelper::getSupportedPlaybackAudioConfig()), + ::testing::Values(AudioOutputFlag::NONE)), + &DeviceConfigParameterToString); +INSTANTIATE_TEST_CASE_P( + RecommendedOutputStreamConfigSupport, OutputStreamTest, + ::testing::Combine( + ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()), + ::testing::ValuesIn(ConfigHelper::getRecommendedSupportPlaybackAudioConfig()), + ::testing::Values(AudioOutputFlag::NONE)), + &DeviceConfigParameterToString); +#elif MAJOR_VERSION >= 6 +// For V6 and above test according to the audio policy manager configuration. +// This is more correct as CDD is written from the apps perspective. +// Audio system provides necessary format conversions for the missing configurations. +INSTANTIATE_TEST_CASE_P(DeclaredOutputStreamConfigSupport, OutputStreamTest, + ::testing::ValuesIn(getOutputDeviceConfigParameters()), + &DeviceConfigParameterToString); +#endif ////////////////////////////// openInputStream ////////////////////////////// class InputStreamTest : public OpenStreamTest { void SetUp() override { ASSERT_NO_FATAL_FAILURE(OpenStreamTest::SetUp()); // setup base - if (IsSkipped()) return; // do not attempt to use 'device' address.device = AudioDevice::IN_DEFAULT; - const AudioConfig& config = GetParam(); - // TODO: test all supported flags and source - auto flags = mkEnumBitfield(AudioInputFlag::NONE); + const AudioConfig& config = getConfig(); + auto flags = getInputFlags(); testOpen( - [&](AudioIoHandle handle, AudioConfig config, auto cb) { - return device->openInputStream(handle, address, config, flags, initMetadata, cb); - }, - config); + [&](AudioIoHandle handle, AudioConfig config, auto cb) { + return getDevice()->openInputStream(handle, address, config, flags, + initMetadata, cb); + }, + config); } protected: @@ -807,19 +981,36 @@ TEST_P(InputStreamTest, OpenInputStreamTest) { "recommended config"); // Open done in setup } +#if MAJOR_VERSION <= 5 +// For V2..5 test the primary device according to CDD requirements. INSTANTIATE_TEST_CASE_P( - RequiredInputStreamConfigSupport, InputStreamTest, - ::testing::ValuesIn(AudioConfigPrimaryTest::getRequiredSupportCaptureAudioConfig()), - &generateTestName); + RequiredInputStreamConfigSupport, InputStreamTest, + ::testing::Combine( + ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()), + ::testing::ValuesIn(ConfigHelper::getRequiredSupportCaptureAudioConfig()), + ::testing::Values(AudioInputFlag::NONE)), + &DeviceConfigParameterToString); INSTANTIATE_TEST_CASE_P( - SupportedInputStreamConfig, InputStreamTest, - ::testing::ValuesIn(AudioConfigPrimaryTest::getSupportedCaptureAudioConfig()), - &generateTestName); - + SupportedInputStreamConfig, InputStreamTest, + ::testing::Combine(::testing::ValuesIn(getDeviceParameters()), + ::testing::ValuesIn(ConfigHelper::getSupportedCaptureAudioConfig()), + ::testing::Values(AudioInputFlag::NONE)), + &DeviceConfigParameterToString); INSTANTIATE_TEST_CASE_P( - RecommendedInputStreamConfigSupport, InputStreamTest, - ::testing::ValuesIn(AudioConfigPrimaryTest::getRecommendedSupportCaptureAudioConfig()), - &generateTestName); + RecommendedInputStreamConfigSupport, InputStreamTest, + ::testing::Combine( + ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()), + ::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig()), + ::testing::Values(AudioInputFlag::NONE)), + &DeviceConfigParameterToString); +#elif MAJOR_VERSION >= 6 +// For V6 and above test according to the audio policy manager configuration. +// This is more correct as CDD is written from the apps perspective. +// Audio system provides necessary format conversions for the missing configurations. +INSTANTIATE_TEST_CASE_P(DeclaredInputStreamConfigSupport, InputStreamTest, + ::testing::ValuesIn(getInputDeviceConfigParameters()), + &DeviceConfigParameterToString); +#endif ////////////////////////////////////////////////////////////////////////////// ////////////////////////////// IStream getters /////////////////////////////// @@ -1332,35 +1523,39 @@ TEST_P(OutputStreamTest, GetPresentationPositionStop) { /////////////////////////////// PrimaryDevice //////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -TEST_F(AudioPrimaryHidlTest, setVoiceVolume) { +TEST_P(AudioPrimaryHidlTest, setVoiceVolume) { doc::test("Make sure setVoiceVolume only succeed if volume is in [0,1]"); - testUnitaryGain([](float volume) { return device->setVoiceVolume(volume); }); + testUnitaryGain([this](float volume) { return getDevice()->setVoiceVolume(volume); }); } -TEST_F(BoolAccessorPrimaryHidlTest, BtScoNrecEnabled) { +TEST_P(BoolAccessorPrimaryHidlTest, BtScoNrecEnabled) { doc::test("Query and set the BT SCO NR&EC state"); testAccessors("BtScoNrecEnabled", Initial{false, OPTIONAL}, {true}, &IPrimaryDevice::setBtScoNrecEnabled, &IPrimaryDevice::getBtScoNrecEnabled); } -TEST_F(BoolAccessorPrimaryHidlTest, setGetBtScoWidebandEnabled) { +TEST_P(BoolAccessorPrimaryHidlTest, setGetBtScoWidebandEnabled) { doc::test("Query and set the SCO whideband state"); testAccessors("BtScoWideband", Initial{false, OPTIONAL}, {true}, &IPrimaryDevice::setBtScoWidebandEnabled, &IPrimaryDevice::getBtScoWidebandEnabled); } -using TtyModeAccessorPrimaryHidlTest = AccessorPrimaryHidlTest; -TEST_F(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) { +using TtyModeAccessorPrimaryHidlTest = + AccessorHidlTest; +TEST_P(TtyModeAccessorPrimaryHidlTest, setGetTtyMode) { doc::test("Query and set the TTY mode state"); testAccessors( "TTY mode", Initial{IPrimaryDevice::TtyMode::OFF}, {IPrimaryDevice::TtyMode::HCO, IPrimaryDevice::TtyMode::VCO, IPrimaryDevice::TtyMode::FULL}, &IPrimaryDevice::setTtyMode, &IPrimaryDevice::getTtyMode); } +INSTANTIATE_TEST_CASE_P(TtyModeAccessorPrimaryHidl, TtyModeAccessorPrimaryHidlTest, + ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()), + &DeviceParameterToString); -TEST_F(BoolAccessorPrimaryHidlTest, setGetHac) { +TEST_P(BoolAccessorPrimaryHidlTest, setGetHac) { doc::test("Query and set the HAC state"); testAccessors("HAC", Initial{false}, {true}, &IPrimaryDevice::setHacEnabled, &IPrimaryDevice::getHacEnabled); @@ -1372,9 +1567,13 @@ TEST_F(BoolAccessorPrimaryHidlTest, setGetHac) { int main(int argc, char** argv) { environment = new AudioHidlTestEnvironment; + // For V2..5 it's critical to initialize environment before GTest. + // The environment parses the service name from the command line, + // then it can be used in GTest parameter generators which are + // initialized during the call to InitGoogleTest. + environment->init(&argc, argv); ::testing::AddGlobalTestEnvironment(environment); ::testing::InitGoogleTest(&argc, argv); - environment->init(&argc, argv); int status = RUN_ALL_TESTS(); return status; } diff --git a/audio/core/all-versions/vts/functional/ConfigHelper.h b/audio/core/all-versions/vts/functional/ConfigHelper.h new file mode 100644 index 0000000000..48aae8c5b3 --- /dev/null +++ b/audio/core/all-versions/vts/functional/ConfigHelper.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2019 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. + */ + +// Code in this file uses 'getCachedPolicyConfig' +#ifndef AUDIO_PRIMARY_HIDL_HAL_TEST +#error Must be included from AudioPrimaryHidlTest.h +#endif + +////////////////////////////////////////////////////////////////////////////// +//////////////// Required and recommended audio format support /////////////// +// From: +// https://source.android.com/compatibility/android-cdd.html#5_4_audio_recording +// From: +// https://source.android.com/compatibility/android-cdd.html#5_5_audio_playback +/////////// TODO: move to the beginning of the file for easier update //////// +////////////////////////////////////////////////////////////////////////////// + +struct ConfigHelper { + // for retro compatibility only test the primary device IN_BUILTIN_MIC + // FIXME: in the next audio HAL version, test all available devices + static bool primaryHasMic() { + auto& policyConfig = getCachedPolicyConfig(); + if (policyConfig.getStatus() != OK || policyConfig.getPrimaryModule() == nullptr) { + return true; // Could not get the information, run all tests + } + auto getMic = [](auto& devs) { + return devs.getDevice(AUDIO_DEVICE_IN_BUILTIN_MIC, {}, AUDIO_FORMAT_DEFAULT); + }; + auto primaryMic = getMic(policyConfig.getPrimaryModule()->getDeclaredDevices()); + auto availableMic = getMic(policyConfig.getAvailableInputDevices()); + + return primaryMic != nullptr && primaryMic->equals(availableMic); + } + + // Cache result ? + static const vector getRequiredSupportPlaybackAudioConfig() { + return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, + {8000, 11025, 16000, 22050, 32000, 44100}, + {AudioFormat::PCM_16_BIT}); + } + + static const vector getRecommendedSupportPlaybackAudioConfig() { + return combineAudioConfig({AudioChannelMask::OUT_STEREO, AudioChannelMask::OUT_MONO}, + {24000, 48000}, {AudioFormat::PCM_16_BIT}); + } + + static const vector getSupportedPlaybackAudioConfig() { + // TODO: retrieve audio config supported by the platform + // as declared in the policy configuration + return {}; + } + + static const vector getRequiredSupportCaptureAudioConfig() { + if (!primaryHasMic()) return {}; + return combineAudioConfig({AudioChannelMask::IN_MONO}, {8000, 11025, 16000, 44100}, + {AudioFormat::PCM_16_BIT}); + } + static const vector getRecommendedSupportCaptureAudioConfig() { + if (!primaryHasMic()) return {}; + return combineAudioConfig({AudioChannelMask::IN_STEREO}, {22050, 48000}, + {AudioFormat::PCM_16_BIT}); + } + static const vector getSupportedCaptureAudioConfig() { + // TODO: retrieve audio config supported by the platform + // as declared in the policy configuration + return {}; + } + + static vector combineAudioConfig(vector channelMasks, + vector sampleRates, + audio_format_t format) { + vector configs; + configs.reserve(channelMasks.size() * sampleRates.size()); + for (auto channelMask : channelMasks) { + for (auto sampleRate : sampleRates) { + AudioConfig config{}; + // leave offloadInfo to 0 + config.channelMask = EnumBitfield(channelMask); + config.sampleRateHz = sampleRate; + config.format = AudioFormat(format); + configs.push_back(config); + } + } + return configs; + } + + static vector combineAudioConfig(vector channelMasks, + vector sampleRates, + vector formats) { + vector configs; + configs.reserve(channelMasks.size() * sampleRates.size() * formats.size()); + for (auto channelMask : channelMasks) { + for (auto sampleRate : sampleRates) { + for (auto format : formats) { + AudioConfig config{}; + // leave offloadInfo to 0 + config.channelMask = mkEnumBitfield(channelMask); + config.sampleRateHz = sampleRate; + config.format = format; + // FIXME: leave frameCount to 0 ? + configs.push_back(config); + } + } + } + return configs; + } +}; diff --git a/audio/core/all-versions/vts/functional/DeviceManager.h b/audio/core/all-versions/vts/functional/DeviceManager.h new file mode 100644 index 0000000000..b6e2db0685 --- /dev/null +++ b/audio/core/all-versions/vts/functional/DeviceManager.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2019 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. + */ + +// Code in this file uses 'environment' +#ifndef AUDIO_PRIMARY_HIDL_HAL_TEST +#error Must be included from AudioPrimaryHidlTest.h +#endif + +template +class InterfaceManager { + public: + sp get(const Key& name) { + auto existing = instances.find(name); + if (existing != instances.end()) return existing->second; + auto [inserted, _] = instances.emplace(name, Derived::createInterfaceInstance(name)); + if (inserted->second) { + environment->registerTearDown([name]() { (void)Derived::getInstance().reset(name); }); + } + return inserted->second; + } + + // The test must check that reset was successful. Reset failure means that the test code + // is holding a strong reference to the device. + bool reset(const Key& name) __attribute__((warn_unused_result)) { + auto iter = instances.find(name); + if (iter == instances.end()) return true; + ::android::wp weak = iter->second; + instances.erase(iter); + if (weak.promote() != nullptr) return false; + waitForInstanceDestruction(); + return true; + } + + static void waitForInstanceDestruction() { + // FIXME: there is no way to know when the remote IDevice is being destroyed + // Binder does not support testing if an object is alive, thus + // wait for 100ms to let the binder destruction propagates and + // the remote device has the time to be destroyed. + // flushCommand makes sure all local command are sent, thus should reduce + // the latency between local and remote destruction. + IPCThreadState::self()->flushCommands(); + usleep(100 * 1000); + } + + protected: + std::map> instances; +}; + +class DevicesFactoryManager + : public InterfaceManager { + public: + static DevicesFactoryManager& getInstance() { + static DevicesFactoryManager instance; + return instance; + } + static sp createInterfaceInstance(const std::string& name) { +#if MAJOR_VERSION <= 5 + return ::testing::VtsHalHidlTargetTestBase::getService(name); +#elif MAJOR_VERSION >= 6 + return IDevicesFactory::getService(name); +#endif + } +}; + +using FactoryAndDevice = std::tuple; +class DeviceManager : public InterfaceManager { + public: + static DeviceManager& getInstance() { + static DeviceManager instance; + return instance; + } + static sp createInterfaceInstance(const FactoryAndDevice& factoryAndDevice) { + auto [factoryName, name] = factoryAndDevice; + sp factory = DevicesFactoryManager::getInstance().get(factoryName); + return name == kPrimaryDevice ? openPrimaryDevice(factory) : openDevice(factory, name); + } + using InterfaceManager::reset; + + static constexpr const char* kPrimaryDevice = "primary"; + + sp get(const std::string& factoryName, const std::string& name) { + return InterfaceManager::get(std::make_tuple(factoryName, name)); + } + sp getPrimary(const std::string& factoryName) { + sp device = get(factoryName, kPrimaryDevice); + return device != nullptr ? IPrimaryDevice::castFrom(device) : nullptr; + } + bool reset(const std::string& factoryName, const std::string& name) + __attribute__((warn_unused_result)) { + return InterfaceManager::reset(std::make_tuple(factoryName, name)); + } + bool resetPrimary(const std::string& factoryName) __attribute__((warn_unused_result)) { + return reset(factoryName, kPrimaryDevice); + } + + private: + static sp openDevice(const sp& factory, const std::string& name) { + if (factory == nullptr) return nullptr; + sp device; +#if MAJOR_VERSION >= 4 + Result result; + auto ret = factory->openDevice(name, returnIn(result, device)); + if (!ret.isOk() || result != Result::OK || device == nullptr) { + ALOGW("Device %s can not be opened, transaction: %s, result %d, device %p", + name.c_str(), ret.description().c_str(), result, device.get()); + return nullptr; + } +#else + (void)name; +#endif + return device; + } + + static sp openPrimaryDevice(const sp& factory) { + if (factory == nullptr) return nullptr; + Result result; + sp device; +#if MAJOR_VERSION == 2 + auto ret = factory->openDevice(IDevicesFactory::Device::PRIMARY, returnIn(result, device)); +#elif MAJOR_VERSION >= 4 + auto ret = factory->openPrimaryDevice(returnIn(result, device)); +#endif + if (!ret.isOk() || result != Result::OK || device == nullptr) { + ALOGW("Primary device can not be opened, transaction: %s, result %d, device %p", + ret.description().c_str(), result, device.get()); + return nullptr; + } + return device; + } +}; diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp index c4c7f7ccc4..3c712b5ca3 100644 --- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp +++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp @@ -28,8 +28,14 @@ #include +#if MAJOR_VERSION <= 5 #include #include +#elif MAJOR_VERSION >= 6 +#include +#include +#include +#endif using ::android::sp; using ::android::hardware::hidl_handle; @@ -49,6 +55,11 @@ using namespace ::android::hardware::audio::effect::CPP_VERSION; #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) #endif +#if MAJOR_VERSION <= 5 +// For HAL versions 2..5 Vts Environment and Test base classes are used. +// The tests are non-parametrized. +#define EFFECT_TEST TEST_F + // Test environment for Audio Effects Factory HIDL HAL. class AudioEffectsFactoryHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase { public: @@ -71,6 +82,18 @@ class AudioEffectsFactoryHidlTest : public ::testing::VtsHalHidlTargetTestBase { ASSERT_NE(effectsFactory, nullptr); } +#elif MAJOR_VERSION >= 6 +// For HAL version 6 and above, standard GTest Environment and Test base classes are used. +// The tests are parametrized by the IEffectsFactory instance name. +#define EFFECT_TEST TEST_P + +class AudioEffectsFactoryHidlTest : public ::testing::TestWithParam { + public: + void SetUp() override { + effectsFactory = IEffectsFactory::getService(GetParam()); + ASSERT_NE(effectsFactory, nullptr); + } +#endif // The rest of the AudioEffectsFactoryHidlTest class definition is the same. void TearDown() override { effectsFactory.clear(); } protected: @@ -81,7 +104,7 @@ class AudioEffectsFactoryHidlTest : public ::testing::VtsHalHidlTargetTestBase { sp effectsFactory; }; -TEST_F(AudioEffectsFactoryHidlTest, EnumerateEffects) { +EFFECT_TEST(AudioEffectsFactoryHidlTest, EnumerateEffects) { description("Verify that EnumerateEffects returns at least one effect"); Result retval = Result::NOT_INITIALIZED; size_t effectCount = 0; @@ -95,7 +118,7 @@ TEST_F(AudioEffectsFactoryHidlTest, EnumerateEffects) { EXPECT_GT(effectCount, 0u); } -TEST_F(AudioEffectsFactoryHidlTest, CreateEffect) { +EFFECT_TEST(AudioEffectsFactoryHidlTest, CreateEffect) { description("Verify that an effect can be created via CreateEffect"); bool gotEffect = false; Uuid effectUuid; @@ -123,7 +146,7 @@ TEST_F(AudioEffectsFactoryHidlTest, CreateEffect) { EXPECT_NE(nullptr, effect.get()); } -TEST_F(AudioEffectsFactoryHidlTest, GetDescriptor) { +EFFECT_TEST(AudioEffectsFactoryHidlTest, GetDescriptor) { description( "Verify that effects factory can provide an effect descriptor via " "GetDescriptor"); @@ -146,7 +169,7 @@ TEST_F(AudioEffectsFactoryHidlTest, GetDescriptor) { EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectsFactoryHidlTest, DebugDumpInvalidArgument) { +EFFECT_TEST(AudioEffectsFactoryHidlTest, DebugDumpInvalidArgument) { description("Verify that debugDump doesn't crash on invalid arguments"); #if MAJOR_VERSION == 2 Return ret = effectsFactory->debugDump(hidl_handle()); @@ -168,10 +191,17 @@ static const Uuid LOUDNESS_ENHANCER_EFFECT_TYPE = { std::array{{0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}}}; // The main test class for Audio Effect HIDL HAL. +#if MAJOR_VERSION <= 5 class AudioEffectHidlTest : public ::testing::VtsHalHidlTargetTestBase { public: void SetUp() override { effectsFactory = ::testing::VtsHalHidlTargetTestBase::getService(); +#elif MAJOR_VERSION >= 6 +class AudioEffectHidlTest : public ::testing::TestWithParam { + public: + void SetUp() override { + effectsFactory = IEffectsFactory::getService(GetParam()); +#endif ASSERT_NE(nullptr, effectsFactory.get()); findAndCreateEffect(getEffectType()); @@ -250,14 +280,14 @@ void AudioEffectHidlTest::getChannelCount(uint32_t* channelCount) { static_cast(currentConfig.outputCfg.channels)); } -TEST_F(AudioEffectHidlTest, Close) { +EFFECT_TEST(AudioEffectHidlTest, Close) { description("Verify that an effect can be closed"); Return ret = effect->close(); EXPECT_TRUE(ret.isOk()); EXPECT_EQ(Result::OK, ret); } -TEST_F(AudioEffectHidlTest, GetDescriptor) { +EFFECT_TEST(AudioEffectHidlTest, GetDescriptor) { description("Verify that an effect can return its own descriptor via GetDescriptor"); Result retval = Result::NOT_INITIALIZED; Uuid actualType; @@ -272,7 +302,7 @@ TEST_F(AudioEffectHidlTest, GetDescriptor) { EXPECT_EQ(getEffectType(), actualType); } -TEST_F(AudioEffectHidlTest, GetSetConfig) { +EFFECT_TEST(AudioEffectHidlTest, GetSetConfig) { description( "Verify that it is possible to manipulate effect config via Get / " "SetConfig"); @@ -291,26 +321,26 @@ TEST_F(AudioEffectHidlTest, GetSetConfig) { EXPECT_EQ(Result::OK, ret2); } -TEST_F(AudioEffectHidlTest, GetConfigReverse) { +EFFECT_TEST(AudioEffectHidlTest, GetConfigReverse) { description("Verify that GetConfigReverse does not crash"); Return ret = effect->getConfigReverse([&](Result, const EffectConfig&) {}); EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectHidlTest, GetSupportedAuxChannelsConfigs) { +EFFECT_TEST(AudioEffectHidlTest, GetSupportedAuxChannelsConfigs) { description("Verify that GetSupportedAuxChannelsConfigs does not crash"); Return ret = effect->getSupportedAuxChannelsConfigs( 0, [&](Result, const hidl_vec&) {}); EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectHidlTest, GetAuxChannelsConfig) { +EFFECT_TEST(AudioEffectHidlTest, GetAuxChannelsConfig) { description("Verify that GetAuxChannelsConfig does not crash"); Return ret = effect->getAuxChannelsConfig([&](Result, const EffectAuxChannelsConfig&) {}); EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectHidlTest, SetAuxChannelsConfig) { +EFFECT_TEST(AudioEffectHidlTest, SetAuxChannelsConfig) { description("Verify that SetAuxChannelsConfig does not crash"); Return ret = effect->setAuxChannelsConfig(EffectAuxChannelsConfig()); EXPECT_TRUE(ret.isOk()); @@ -349,7 +379,7 @@ inline bool operator==(const EffectConfig& lhs, const EffectConfig& rhs) { } // namespace hardware } // namespace android -TEST_F(AudioEffectHidlTest, Reset) { +EFFECT_TEST(AudioEffectHidlTest, Reset) { description("Verify that Reset preserves effect configuration"); Result retval = Result::NOT_INITIALIZED; EffectConfig originalConfig; @@ -374,7 +404,7 @@ TEST_F(AudioEffectHidlTest, Reset) { EXPECT_EQ(originalConfig, configAfterReset); } -TEST_F(AudioEffectHidlTest, DisableEnableDisable) { +EFFECT_TEST(AudioEffectHidlTest, DisableEnableDisable) { description("Verify Disable -> Enable -> Disable sequence for an effect"); Return ret = effect->disable(); EXPECT_TRUE(ret.isOk()); @@ -387,14 +417,14 @@ TEST_F(AudioEffectHidlTest, DisableEnableDisable) { EXPECT_EQ(Result::OK, ret); } -TEST_F(AudioEffectHidlTest, SetDevice) { +EFFECT_TEST(AudioEffectHidlTest, SetDevice) { description("Verify that SetDevice works for an output chain effect"); Return ret = effect->setDevice(mkEnumBitfield(AudioDevice::OUT_SPEAKER)); EXPECT_TRUE(ret.isOk()); EXPECT_EQ(Result::OK, ret); } -TEST_F(AudioEffectHidlTest, SetAndGetVolume) { +EFFECT_TEST(AudioEffectHidlTest, SetAndGetVolume) { description("Verify that SetAndGetVolume method works for an effect"); uint32_t channelCount; getChannelCount(&channelCount); @@ -410,7 +440,7 @@ TEST_F(AudioEffectHidlTest, SetAndGetVolume) { EXPECT_EQ(Result::OK, retval); } -TEST_F(AudioEffectHidlTest, VolumeChangeNotification) { +EFFECT_TEST(AudioEffectHidlTest, VolumeChangeNotification) { description("Verify that effect accepts VolumeChangeNotification"); uint32_t channelCount; getChannelCount(&channelCount); @@ -424,32 +454,32 @@ TEST_F(AudioEffectHidlTest, VolumeChangeNotification) { EXPECT_EQ(Result::OK, ret); } -TEST_F(AudioEffectHidlTest, SetAudioMode) { +EFFECT_TEST(AudioEffectHidlTest, SetAudioMode) { description("Verify that SetAudioMode works for an effect"); Return ret = effect->setAudioMode(AudioMode::NORMAL); EXPECT_TRUE(ret.isOk()); EXPECT_EQ(Result::OK, ret); } -TEST_F(AudioEffectHidlTest, SetConfigReverse) { +EFFECT_TEST(AudioEffectHidlTest, SetConfigReverse) { description("Verify that SetConfigReverse does not crash"); Return ret = effect->setConfigReverse(EffectConfig(), nullptr, nullptr); EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectHidlTest, SetInputDevice) { +EFFECT_TEST(AudioEffectHidlTest, SetInputDevice) { description("Verify that SetInputDevice does not crash"); Return ret = effect->setInputDevice(mkEnumBitfield(AudioDevice::IN_BUILTIN_MIC)); EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectHidlTest, SetAudioSource) { +EFFECT_TEST(AudioEffectHidlTest, SetAudioSource) { description("Verify that SetAudioSource does not crash"); Return ret = effect->setAudioSource(AudioSource::MIC); EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectHidlTest, Offload) { +EFFECT_TEST(AudioEffectHidlTest, Offload) { description("Verify that calling Offload method does not crash"); EffectOffloadParameter offloadParam; offloadParam.isOffload = false; @@ -458,7 +488,7 @@ TEST_F(AudioEffectHidlTest, Offload) { EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectHidlTest, PrepareForProcessing) { +EFFECT_TEST(AudioEffectHidlTest, PrepareForProcessing) { description("Verify that PrepareForProcessing method works for an effect"); Result retval = Result::NOT_INITIALIZED; Return ret = effect->prepareForProcessing( @@ -467,7 +497,7 @@ TEST_F(AudioEffectHidlTest, PrepareForProcessing) { EXPECT_EQ(Result::OK, retval); } -TEST_F(AudioEffectHidlTest, SetProcessBuffers) { +EFFECT_TEST(AudioEffectHidlTest, SetProcessBuffers) { description("Verify that SetProcessBuffers works for an effect"); sp ashmem = IAllocator::getService("ashmem"); ASSERT_NE(nullptr, ashmem.get()); @@ -486,41 +516,41 @@ TEST_F(AudioEffectHidlTest, SetProcessBuffers) { EXPECT_EQ(Result::OK, ret2); } -TEST_F(AudioEffectHidlTest, Command) { +EFFECT_TEST(AudioEffectHidlTest, Command) { description("Verify that Command does not crash"); Return ret = effect->command(0, hidl_vec(), 0, [&](int32_t, const hidl_vec&) {}); EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectHidlTest, SetParameter) { +EFFECT_TEST(AudioEffectHidlTest, SetParameter) { description("Verify that SetParameter does not crash"); Return ret = effect->setParameter(hidl_vec(), hidl_vec()); EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectHidlTest, GetParameter) { +EFFECT_TEST(AudioEffectHidlTest, GetParameter) { description("Verify that GetParameter does not crash"); Return ret = effect->getParameter(hidl_vec(), 0, [&](Result, const hidl_vec&) {}); EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectHidlTest, GetSupportedConfigsForFeature) { +EFFECT_TEST(AudioEffectHidlTest, GetSupportedConfigsForFeature) { description("Verify that GetSupportedConfigsForFeature does not crash"); Return ret = effect->getSupportedConfigsForFeature( 0, 0, 0, [&](Result, uint32_t, const hidl_vec&) {}); EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectHidlTest, GetCurrentConfigForFeature) { +EFFECT_TEST(AudioEffectHidlTest, GetCurrentConfigForFeature) { description("Verify that GetCurrentConfigForFeature does not crash"); Return ret = effect->getCurrentConfigForFeature(0, 0, [&](Result, const hidl_vec&) {}); EXPECT_TRUE(ret.isOk()); } -TEST_F(AudioEffectHidlTest, SetCurrentConfigForFeature) { +EFFECT_TEST(AudioEffectHidlTest, SetCurrentConfigForFeature) { description("Verify that SetCurrentConfigForFeature does not crash"); Return ret = effect->setCurrentConfigForFeature(0, hidl_vec()); EXPECT_TRUE(ret.isOk()); @@ -606,21 +636,21 @@ void EqualizerAudioEffectHidlTest::getPresetCount(size_t* count) { ASSERT_EQ(Result::OK, retval); } -TEST_F(EqualizerAudioEffectHidlTest, GetNumBands) { +EFFECT_TEST(EqualizerAudioEffectHidlTest, GetNumBands) { description("Verify that Equalizer effect reports at least one band"); uint16_t numBands = 0; getNumBands(&numBands); EXPECT_GT(numBands, 0); } -TEST_F(EqualizerAudioEffectHidlTest, GetLevelRange) { +EFFECT_TEST(EqualizerAudioEffectHidlTest, GetLevelRange) { description("Verify that Equalizer effect reports adequate band level range"); int16_t minLevel = 0x7fff, maxLevel = 0; getLevelRange(&minLevel, &maxLevel); EXPECT_GT(maxLevel, minLevel); } -TEST_F(EqualizerAudioEffectHidlTest, GetSetBandLevel) { +EFFECT_TEST(EqualizerAudioEffectHidlTest, GetSetBandLevel) { description("Verify that manipulating band levels works for Equalizer effect"); uint16_t numBands = 0; getNumBands(&numBands); @@ -649,7 +679,7 @@ TEST_F(EqualizerAudioEffectHidlTest, GetSetBandLevel) { } } -TEST_F(EqualizerAudioEffectHidlTest, GetBandCenterFrequencyAndRange) { +EFFECT_TEST(EqualizerAudioEffectHidlTest, GetBandCenterFrequencyAndRange) { description("Verify that Equalizer effect reports adequate band frequency range"); uint16_t numBands = 0; getNumBands(&numBands); @@ -664,7 +694,7 @@ TEST_F(EqualizerAudioEffectHidlTest, GetBandCenterFrequencyAndRange) { } } -TEST_F(EqualizerAudioEffectHidlTest, GetBandForFrequency) { +EFFECT_TEST(EqualizerAudioEffectHidlTest, GetBandForFrequency) { description("Verify that Equalizer effect supports GetBandForFrequency correctly"); uint16_t numBands = 0; getNumBands(&numBands); @@ -693,14 +723,14 @@ TEST_F(EqualizerAudioEffectHidlTest, GetBandForFrequency) { } } -TEST_F(EqualizerAudioEffectHidlTest, GetPresetNames) { +EFFECT_TEST(EqualizerAudioEffectHidlTest, GetPresetNames) { description("Verify that Equalizer effect reports at least one preset"); size_t presetCount; getPresetCount(&presetCount); EXPECT_GT(presetCount, 0u); } -TEST_F(EqualizerAudioEffectHidlTest, GetSetCurrentPreset) { +EFFECT_TEST(EqualizerAudioEffectHidlTest, GetSetCurrentPreset) { description("Verify that manipulating the current preset for Equalizer effect"); size_t presetCount; getPresetCount(&presetCount); @@ -723,7 +753,7 @@ TEST_F(EqualizerAudioEffectHidlTest, GetSetCurrentPreset) { } } -TEST_F(EqualizerAudioEffectHidlTest, GetSetAllProperties) { +EFFECT_TEST(EqualizerAudioEffectHidlTest, GetSetAllProperties) { description( "Verify that setting band levels and presets works via Get / " "SetAllProperties for Equalizer effect"); @@ -787,7 +817,7 @@ class LoudnessEnhancerAudioEffectHidlTest : public AudioEffectHidlTest { sp enhancer; }; -TEST_F(LoudnessEnhancerAudioEffectHidlTest, GetSetTargetGain) { +EFFECT_TEST(LoudnessEnhancerAudioEffectHidlTest, GetSetTargetGain) { description( "Verify that manipulating the target gain works for Loudness Enhancer " "effect"); @@ -808,6 +838,7 @@ TEST_F(LoudnessEnhancerAudioEffectHidlTest, GetSetTargetGain) { EXPECT_EQ(gain, actualGain); } +#if MAJOR_VERSION <= 5 int main(int argc, char** argv) { ::testing::AddGlobalTestEnvironment(AudioEffectsFactoryHidlEnvironment::Instance()); ::testing::InitGoogleTest(&argc, argv); @@ -816,3 +847,17 @@ int main(int argc, char** argv) { LOG(INFO) << "Test result = " << status; return status; } +#elif MAJOR_VERSION >= 6 +INSTANTIATE_TEST_SUITE_P( + EffectsFactory, AudioEffectsFactoryHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames(IEffectsFactory::descriptor)), + android::hardware::PrintInstanceNameToString); +INSTANTIATE_TEST_SUITE_P( + Equalizer, EqualizerAudioEffectHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames(IEffectsFactory::descriptor)), + android::hardware::PrintInstanceNameToString); +INSTANTIATE_TEST_SUITE_P( + LoudnessEnhancer, LoudnessEnhancerAudioEffectHidlTest, + testing::ValuesIn(android::hardware::getAllHalInstanceNames(IEffectsFactory::descriptor)), + android::hardware::PrintInstanceNameToString); +#endif