blob: e644fd4860d5a64fc96d54812139c857d0bf485c [file] [log] [blame]
/*
* Copyright (C) 2018 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.
*/
// To run this test (as root):
// 1) Build it
// 2) adb push to /vendor/bin
// 3) adb shell /vendor/bin/r_submix_tests
#define LOG_TAG "RemoteSubmixTest"
#include <memory>
#include <gtest/gtest.h>
#include <hardware/audio.h>
#include <utils/Errors.h>
#include <utils/Log.h>
using namespace android;
static status_t load_audio_interface(const char *if_name, audio_hw_device_t **dev)
{
const hw_module_t *mod;
int rc;
rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
if (rc) {
ALOGE("%s couldn't load audio hw module %s.%s (%s)", __func__,
AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
goto out;
}
rc = audio_hw_device_open(mod, dev);
if (rc) {
ALOGE("%s couldn't open audio hw device in %s.%s (%s)", __func__,
AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
goto out;
}
if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN) {
ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
rc = BAD_VALUE;
audio_hw_device_close(*dev);
goto out;
}
return OK;
out:
*dev = NULL;
return rc;
}
class RemoteSubmixTest : public testing::Test {
protected:
void SetUp() override;
void TearDown() override;
void OpenInputStream(const char *address, audio_stream_in_t** streamIn);
void OpenOutputStream(const char *address, audio_stream_out_t** streamOut);
void WriteIntoStream(audio_stream_out_t* streamOut, size_t bufferSize, size_t repeats);
audio_hw_device_t* mDev;
};
void RemoteSubmixTest::SetUp() {
mDev = nullptr;
ASSERT_EQ(OK, load_audio_interface(AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, &mDev));
ASSERT_NE(nullptr, mDev);
}
void RemoteSubmixTest::TearDown() {
if (mDev != nullptr) {
int status = audio_hw_device_close(mDev);
mDev = nullptr;
ALOGE_IF(status, "Error closing audio hw device %p: %s", mDev, strerror(-status));
ASSERT_EQ(0, status);
}
}
void RemoteSubmixTest::OpenInputStream(const char *address, audio_stream_in_t** streamIn) {
*streamIn = nullptr;
struct audio_config configIn = {};
configIn.channel_mask = AUDIO_CHANNEL_IN_MONO;
configIn.sample_rate = 48000;
status_t result = mDev->open_input_stream(mDev,
AUDIO_IO_HANDLE_NONE, AUDIO_DEVICE_NONE, &configIn,
streamIn, AUDIO_INPUT_FLAG_NONE, address, AUDIO_SOURCE_DEFAULT);
ASSERT_EQ(OK, result);
ASSERT_NE(nullptr, *streamIn);
}
void RemoteSubmixTest::OpenOutputStream(const char *address, audio_stream_out_t** streamOut) {
*streamOut = nullptr;
struct audio_config configOut = {};
configOut.channel_mask = AUDIO_CHANNEL_OUT_MONO;
configOut.sample_rate = 48000;
status_t result = mDev->open_output_stream(mDev,
AUDIO_IO_HANDLE_NONE, AUDIO_DEVICE_NONE, AUDIO_OUTPUT_FLAG_NONE,
&configOut, streamOut, address);
ASSERT_EQ(OK, result);
ASSERT_NE(nullptr, *streamOut);
}
void RemoteSubmixTest::WriteIntoStream(
audio_stream_out_t* streamOut, size_t bufferSize, size_t repeats) {
std::unique_ptr<char[]> buffer(new char[bufferSize]);
for (size_t i = 0; i < repeats; ++i) {
ssize_t result = streamOut->write(streamOut, buffer.get(), bufferSize);
EXPECT_EQ(bufferSize, static_cast<size_t>(result));
}
}
TEST_F(RemoteSubmixTest, InitSuccess) {
// SetUp must finish with no assertions.
}
// Verifies that when no input was opened, writing into an output stream does not block.
TEST_F(RemoteSubmixTest, OutputDoesNotBlockWhenNoInput) {
const char *address = "1";
audio_stream_out_t* streamOut;
OpenOutputStream(address, &streamOut);
WriteIntoStream(streamOut, 1024, 16);
mDev->close_output_stream(mDev, streamOut);
}
// Verifies that when input is opened but not reading, writing into an output stream does not block.
// !!! Currently does not finish because requires setting a parameter from another thread !!!
TEST_F(RemoteSubmixTest, OutputDoesNotBlockWhenInputStuck) {
const char *address = "1";
audio_stream_out_t* streamOut;
OpenOutputStream(address, &streamOut);
audio_stream_in_t* streamIn;
OpenInputStream(address, &streamIn);
WriteIntoStream(streamOut, 1024, 16);
mDev->close_input_stream(mDev, streamIn);
mDev->close_output_stream(mDev, streamOut);
}