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

Commit 8613f809 authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

audio: Parametrize core VTS tests

Parametrize tests to accept IDevicesFactory instance name
and IDevice instance name. For audio HAL versions 2..5
the factory instance name is taken from the VTS environment,
and the device is always "primary". For the next versions
the factories are discovered by the test, and the devices
are taken from the audio policy configuration
(to be implemented, see added FIXME comments).

Split the Environment class into two versions: for HAL 2..5
and for next versions. They use different base class.

Move device factories and device caching into dedicated
classes DevicesFactoryManager and DeviceManager. They deal
with instance caching and proper release of server resources.

Bug: 141847510
Bug: 141989952
Test: atest VtsHalAudioV5_0TargetTest
      atest VtsHalAudioV6_0TargetTest
Change-Id: I92c44e0c3f900164dded7e9c4bfc642ca2c335db
parent bc1d5aa0
Loading
Loading
Loading
Loading
+6 −7
Original line number Diff line number Diff line
@@ -20,9 +20,6 @@
#include <functional>
#include <list>

#include <VtsHalHidlTargetTestEnvBase.h>
#include <gtest/gtest.h>

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 {
class EnvironmentTearDown {
  public:
    using TearDownFunc = std::function<void()>;
    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<TearDownFunc> tearDowns;
};

+5 −4
Original line number Diff line number Diff line
@@ -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));
    }
}
+34 −0
Original line number Diff line number Diff line
/*
 * 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 <VtsHalHidlTargetTestEnvBase.h>
#include <gtest/gtest.h>

#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
+29 −42
Original line number Diff line number Diff line
@@ -16,25 +16,14 @@

#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.");
    struct WaitExecutor {
        ~WaitExecutor() { waitForDeviceDestruction(); }
        ~WaitExecutor() { DeviceManager::waitForInstanceDestruction(); }
    } waitExecutor;  // Make sure we wait for the device destruction on exiting from the test.
    Result result;
    sp<IDevice> baseDevice;
    ASSERT_OK(devicesFactory->openDevice("primary", returnIn(result, baseDevice)));
    ASSERT_OK(getDevicesFactory()->openDevice("primary", returnIn(result, baseDevice)));
    if (result != Result::OK && isPrimaryDeviceOptional()) {
        GTEST_SKIP() << "No primary device on this factory";  // returns
    }
@@ -50,10 +39,10 @@ TEST_F(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) {
/////////////////////////// get(Active)Microphones ///////////////////////////
//////////////////////////////////////////////////////////////////////////////

TEST_F(AudioPrimaryHidlTest, GetMicrophonesTest) {
TEST_P(AudioPrimaryHidlTest, GetMicrophonesTest) {
    doc::test("Make sure getMicrophones always succeeds");
    hidl_vec<MicrophoneInfo> microphones;
    ASSERT_OK(device->getMicrophones(returnIn(res, microphones)));
    ASSERT_OK(getDevice()->getMicrophones(returnIn(res, microphones)));
    ASSERT_OK(res);
    if (microphones.size() > 0) {
        // When there is microphone on the phone, try to open an input stream
@@ -75,14 +64,14 @@ TEST_F(AudioPrimaryHidlTest, GetMicrophonesTest) {
            }
            sp<IStreamIn> stream;
            AudioConfig suggestedConfig{};
            ASSERT_OK(device->openInputStream(ioHandle, microphone.deviceAddress, config, flags,
                                              initMetadata,
            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,
                ASSERT_OK(getDevice()->openInputStream(
                        ioHandle, microphone.deviceAddress, suggestedConfig, flags, initMetadata,
                        returnIn(res, stream, suggestedConfigRetry)));
            }
            ASSERT_OK(res);
@@ -131,7 +120,7 @@ TEST_F(AudioPrimaryHidlTest, GetMicrophonesTest) {
    }
}

TEST_F(AudioPrimaryHidlTest, SetConnectedState) {
TEST_P(AudioPrimaryHidlTest, 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 +129,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 +142,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(DeviceManager::getInstance().resetPrimary(getFactoryName()));
}

static void testGetDevices(IStream* stream, AudioDevice expectedDevice) {
@@ -199,7 +186,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 +246,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)))
        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<OPTIONAL>("BtHfpEnabled", Initial{false, OPTIONAL}, {true},
                            &IPrimaryDevice::setBtHfpEnabled, &IPrimaryDevice::getBtHfpEnabled);
+35 −0
Original line number Diff line number Diff line
/*
 * 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 <gtest/gtest.h>

#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
Loading