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

Commit 04a86634 authored by Mikhail Naganov's avatar Mikhail Naganov
Browse files

audiopolicy: Add patch creation tests

Add a test that verifies rejection of bad parameters for
'createAudioPatch'.

Add a test that creates a patch between mixPort and devicePort.

No bugs have been found this time.

Test: audiopolicy_tests
Change-Id: I431e225d9dba0097e3d73796585dbe7f404d1cec
parent c894bf67
Loading
Loading
Loading
Loading
+21 −17
Original line number Diff line number Diff line
@@ -25,51 +25,55 @@ public:
    virtual ~AudioPolicyTestClient() = default;

    // AudioPolicyClientInterface Implementation
    audio_module_handle_t loadHwModule(const char* /*name*/) override { return 0; }
    audio_module_handle_t loadHwModule(const char* /*name*/) override {
        return AUDIO_MODULE_HANDLE_NONE;
    }
    status_t openOutput(audio_module_handle_t /*module*/,
                        audio_io_handle_t* /*output*/,
                        audio_config_t* /*config*/,
                        audio_devices_t* /*devices*/,
                        const String8& /*address*/,
                        uint32_t* /*latencyMs*/,
                        audio_output_flags_t /*flags*/) override { return 0; }
                        audio_output_flags_t /*flags*/) override { return NO_INIT; }
    audio_io_handle_t openDuplicateOutput(audio_io_handle_t /*output1*/,
                                          audio_io_handle_t /*output2*/) override { return 0; }
    status_t closeOutput(audio_io_handle_t /*output*/) override { return 0; }
    status_t suspendOutput(audio_io_handle_t /*output*/) override { return 0; }
    status_t restoreOutput(audio_io_handle_t /*output*/) override { return 0; }
                                          audio_io_handle_t /*output2*/) override {
        return AUDIO_IO_HANDLE_NONE;
    }
    status_t closeOutput(audio_io_handle_t /*output*/) override { return NO_INIT; }
    status_t suspendOutput(audio_io_handle_t /*output*/) override { return NO_INIT; }
    status_t restoreOutput(audio_io_handle_t /*output*/) override { return NO_INIT; }
    status_t openInput(audio_module_handle_t /*module*/,
                       audio_io_handle_t* /*input*/,
                       audio_config_t* /*config*/,
                       audio_devices_t* /*device*/,
                       const String8& /*address*/,
                       audio_source_t /*source*/,
                       audio_input_flags_t /*flags*/) override { return 0; }
    status_t closeInput(audio_io_handle_t /*input*/) override { return 0; }
                       audio_input_flags_t /*flags*/) override { return NO_INIT; }
    status_t closeInput(audio_io_handle_t /*input*/) override { return NO_INIT; }
    status_t setStreamVolume(audio_stream_type_t /*stream*/,
                             float /*volume*/,
                             audio_io_handle_t /*output*/,
                             int /*delayMs*/) override { return 0; }
    status_t invalidateStream(audio_stream_type_t /*stream*/) override { return 0; }
                             int /*delayMs*/) override { return NO_INIT; }
    status_t invalidateStream(audio_stream_type_t /*stream*/) override { return NO_INIT; }
    void setParameters(audio_io_handle_t /*ioHandle*/,
                       const String8& /*keyValuePairs*/,
                       int /*delayMs*/) override { }
    String8 getParameters(audio_io_handle_t /*ioHandle*/,
                          const String8& /*keys*/) override { return String8(); }
    status_t startTone(audio_policy_tone_t /*tone*/,
                       audio_stream_type_t /*stream*/) override { return 0; }
    status_t stopTone() override { return 0; }
    status_t setVoiceVolume(float /*volume*/, int /*delayMs*/) override { return 0; }
                       audio_stream_type_t /*stream*/) override { return NO_INIT; }
    status_t stopTone() override { return NO_INIT; }
    status_t setVoiceVolume(float /*volume*/, int /*delayMs*/) override { return NO_INIT; }
    status_t moveEffects(audio_session_t /*session*/,
                         audio_io_handle_t /*srcOutput*/,
                         audio_io_handle_t /*dstOutput*/) override { return 0; }
                         audio_io_handle_t /*dstOutput*/) override { return NO_INIT; }
    status_t createAudioPatch(const struct audio_patch* /*patch*/,
                              audio_patch_handle_t* /*handle*/,
                              int /*delayMs*/) override { return 0; }
                              int /*delayMs*/) override { return NO_INIT; }
    status_t releaseAudioPatch(audio_patch_handle_t /*handle*/,
                               int /*delayMs*/) override { return 0; }
                               int /*delayMs*/) override { return NO_INIT; }
    status_t setAudioPortConfig(const struct audio_port_config* /*config*/,
                                int /*delayMs*/) override { return 0; }
                                int /*delayMs*/) override { return NO_INIT; }
    void onAudioPortListUpdate() override { }
    void onAudioPatchListUpdate() override { }
    audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t /*use*/) override { return 0; }
+129 −15
Original line number Diff line number Diff line
@@ -14,6 +14,9 @@
 * limitations under the License.
 */

#include <memory>
#include <set>

#include <gtest/gtest.h>

#include "AudioPolicyTestClient.h"
@@ -21,7 +24,7 @@

using namespace android;

TEST(AudioPolicyManager, InitFailure) {
TEST(AudioPolicyManagerTestInit, Failure) {
    AudioPolicyTestClient client;
    AudioPolicyTestManager manager(&client);
    manager.getConfig().setDefault();
@@ -32,12 +35,13 @@ TEST(AudioPolicyManager, InitFailure) {
}


// A client that provides correct module and IO handles for inputs and outputs.
class AudioPolicyTestClientWithModulesIoHandles : public AudioPolicyTestClient {
class AudioPolicyManagerTestClient : public AudioPolicyTestClient {
  public:
    // AudioPolicyClientInterface implementation
    audio_module_handle_t loadHwModule(const char* /*name*/) override {
        return mNextModule++;
        return mNextModuleHandle++;
    }

    status_t openOutput(audio_module_handle_t module,
                        audio_io_handle_t* output,
                        audio_config_t* /*config*/,
@@ -45,14 +49,15 @@ class AudioPolicyTestClientWithModulesIoHandles : public AudioPolicyTestClient {
                        const String8& /*address*/,
                        uint32_t* /*latencyMs*/,
                        audio_output_flags_t /*flags*/) override {
        if (module >= mNextModule) {
        if (module >= mNextModuleHandle) {
            ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
                    __func__, module, mNextModule);
                    __func__, module, mNextModuleHandle);
            return BAD_VALUE;
        }
        *output = mNextIoHandle++;
        return NO_ERROR;
    }

    status_t openInput(audio_module_handle_t module,
                       audio_io_handle_t* input,
                       audio_config_t* /*config*/,
@@ -60,23 +65,132 @@ class AudioPolicyTestClientWithModulesIoHandles : public AudioPolicyTestClient {
                       const String8& /*address*/,
                       audio_source_t /*source*/,
                       audio_input_flags_t /*flags*/) override {
        if (module >= mNextModule) {
        if (module >= mNextModuleHandle) {
            ALOGE("%s: Module handle %d has not been allocated yet (next is %d)",
                    __func__, module, mNextModule);
                    __func__, module, mNextModuleHandle);
            return BAD_VALUE;
        }
        *input = mNextIoHandle++;
        return NO_ERROR;
    }

    status_t createAudioPatch(const struct audio_patch* /*patch*/,
                              audio_patch_handle_t* handle,
                              int /*delayMs*/) override {
        *handle = mNextPatchHandle++;
        mActivePatches.insert(*handle);
        return NO_ERROR;
    }

    status_t releaseAudioPatch(audio_patch_handle_t handle,
                               int /*delayMs*/) override {
        if (mActivePatches.erase(handle) != 1) {
            if (handle >= mNextPatchHandle) {
                ALOGE("%s: Patch handle %d has not been allocated yet (next is %d)",
                        __func__, handle, mNextPatchHandle);
            } else {
                ALOGE("%s: Attempt to release patch %d twice", __func__, handle);
            }
            return BAD_VALUE;
        }
        return NO_ERROR;
    }

    // Helper methods for tests
    size_t getActivePatchesCount() const { return mActivePatches.size(); }

  private:
    audio_module_handle_t mNextModule = AUDIO_MODULE_HANDLE_NONE + 1;
    audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
    audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
    audio_patch_handle_t mNextPatchHandle = AUDIO_PATCH_HANDLE_NONE + 1;
    std::set<audio_patch_handle_t> mActivePatches;
};

TEST(AudioPolicyManager, InitSuccess) {
    AudioPolicyTestClientWithModulesIoHandles client;
    AudioPolicyTestManager manager(&client);
    manager.getConfig().setDefault();
    ASSERT_EQ(NO_ERROR, manager.initialize());
    ASSERT_EQ(NO_ERROR, manager.initCheck());
class AudioPolicyManagerTest : public testing::Test {
  protected:
    virtual void SetUp();
    virtual void TearDown();

    std::unique_ptr<AudioPolicyManagerTestClient> mClient;
    std::unique_ptr<AudioPolicyTestManager> mManager;
};

void AudioPolicyManagerTest::SetUp() {
    mClient.reset(new AudioPolicyManagerTestClient);
    mManager.reset(new AudioPolicyTestManager(mClient.get()));
    mManager->getConfig().setDefault();
    ASSERT_EQ(NO_ERROR, mManager->initialize());
    ASSERT_EQ(NO_ERROR, mManager->initCheck());
}

void AudioPolicyManagerTest::TearDown() {
    mManager.reset();
    mClient.reset();
}

TEST_F(AudioPolicyManagerTest, InitSuccess) {
    // SetUp must finish with no assertions.
}

TEST_F(AudioPolicyManagerTest, CreateAudioPatchFailure) {
    audio_patch patch{};
    audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
    const size_t patchCountBefore = mClient->getActivePatchesCount();
    ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(nullptr, &handle, 0));
    ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, nullptr, 0));
    ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0));
    patch.num_sources = AUDIO_PATCH_PORTS_MAX + 1;
    patch.num_sinks = 1;
    ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0));
    patch.num_sources = 1;
    patch.num_sinks = AUDIO_PATCH_PORTS_MAX + 1;
    ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0));
    patch.num_sources = 2;
    patch.num_sinks = 1;
    ASSERT_EQ(INVALID_OPERATION, mManager->createAudioPatch(&patch, &handle, 0));
    patch = {};
    patch.num_sources = 1;
    patch.sources[0].role = AUDIO_PORT_ROLE_SINK;
    patch.num_sinks = 1;
    patch.sinks[0].role = AUDIO_PORT_ROLE_SINK;
    ASSERT_EQ(INVALID_OPERATION, mManager->createAudioPatch(&patch, &handle, 0));
    patch = {};
    patch.num_sources = 1;
    patch.sources[0].role = AUDIO_PORT_ROLE_SOURCE;
    patch.num_sinks = 1;
    patch.sinks[0].role = AUDIO_PORT_ROLE_SOURCE;
    ASSERT_EQ(INVALID_OPERATION, mManager->createAudioPatch(&patch, &handle, 0));
    // Verify that the handle is left unchanged.
    ASSERT_EQ(AUDIO_PATCH_HANDLE_NONE, handle);
    ASSERT_EQ(patchCountBefore, mClient->getActivePatchesCount());
}

TEST_F(AudioPolicyManagerTest, CreateAudioPatchFromMix) {
    audio_patch patch{};
    audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
    uid_t uid = 42;
    const size_t patchCountBefore = mClient->getActivePatchesCount();
    patch.num_sources = 1;
    {
        auto& src = patch.sources[0];
        src.role = AUDIO_PORT_ROLE_SOURCE;
        src.type = AUDIO_PORT_TYPE_MIX;
        src.id = mManager->getConfig().getAvailableInputDevices()[0]->getId();
        // Note: these are the parameters of the output device.
        src.sample_rate = 44100;
        src.format = AUDIO_FORMAT_PCM_16_BIT;
        src.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
    }
    patch.num_sinks = 1;
    {
        auto& sink = patch.sinks[0];
        sink.role = AUDIO_PORT_ROLE_SINK;
        sink.type = AUDIO_PORT_TYPE_DEVICE;
        sink.id = mManager->getConfig().getDefaultOutputDevice()->getId();
    }
    ASSERT_EQ(NO_ERROR, mManager->createAudioPatch(&patch, &handle, uid));
    ASSERT_NE(AUDIO_PATCH_HANDLE_NONE, handle);
    ASSERT_EQ(patchCountBefore + 1, mClient->getActivePatchesCount());
}

// TODO: Add patch creation tests that involve already existing patch