* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <benchmark/benchmark.h>
#include <climits>
#include <gtest/gtest.h>
#include "hdf_base.h"
#include "osal_mem.h"
#include "v6_1/iaudio_manager.h"
using namespace testing::ext;
using namespace std;
#define AUDIO_CHANNELCOUNT 2
#define AUDIO_SAMPLE_RATE_48K 48000
#define DEEP_BUFFER_RENDER_PERIOD_SIZE 4096
#define INT_32_MAX 0x7fffffff
#define PCM_16_BIT 16
#define PCM_8_BIT 8
namespace {
static const uint32_t g_audioAdapterNumMax = 5;
const int32_t AUDIO_ADAPTER_BUF_TEST = 1024;
const int32_t ITERATION_FREQUENCY = 100;
const int32_t REPETITION_FREQUENCY = 3;
class AudioAdapterBenchmarkTest : public benchmark::Fixture {
public:
struct IAudioManager *manager_ = nullptr;
struct IAudioAdapter *adapter_ = nullptr;
struct AudioAdapterDescriptor *adapterDescs_ = nullptr;
uint32_t renderId_ = 0;
uint32_t captureId_ = 0;
void SetUp(const ::benchmark::State &state);
void TearDown(const ::benchmark::State &state);
void InitAttrs(struct AudioSampleAttributes &attrs);
void InitDevDesc(struct AudioDeviceDescriptor &devDesc);
void AudioAdapterDescriptorFree(struct AudioAdapterDescriptor *dataBlock, bool freeSelf);
void ReleaseAdapterDescs(struct AudioAdapterDescriptor *descs, uint32_t descsLen);
};
void AudioAdapterBenchmarkTest::AudioAdapterDescriptorFree(struct AudioAdapterDescriptor *dataBlock, bool freeSelf)
{
if (dataBlock == nullptr) {
return;
}
if (dataBlock->adapterName != nullptr) {
OsalMemFree(dataBlock->adapterName);
dataBlock->adapterName = nullptr;
}
if (dataBlock->ports != nullptr) {
OsalMemFree(dataBlock->ports);
}
if (freeSelf) {
OsalMemFree(dataBlock);
}
}
void AudioAdapterBenchmarkTest::ReleaseAdapterDescs(struct AudioAdapterDescriptor *descs, uint32_t descsLen)
{
if ((descs == nullptr) || (descsLen == 0)) {
return;
}
for (uint32_t i = 0; i < descsLen; i++) {
AudioAdapterDescriptorFree(&descs[i], false);
}
}
void AudioAdapterBenchmarkTest::InitAttrs(struct AudioSampleAttributes &attrs)
{
attrs.format = AUDIO_FORMAT_TYPE_PCM_16_BIT;
attrs.channelCount = AUDIO_CHANNELCOUNT;
attrs.sampleRate = AUDIO_SAMPLE_RATE_48K;
attrs.interleaved = 1;
attrs.type = AUDIO_IN_MEDIA;
attrs.period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
attrs.frameSize = PCM_16_BIT * attrs.channelCount / PCM_8_BIT;
attrs.isBigEndian = false;
attrs.isSignedData = true;
attrs.startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (attrs.frameSize);
attrs.stopThreshold = INT_32_MAX;
}
void AudioAdapterBenchmarkTest::InitDevDesc(struct AudioDeviceDescriptor &devDesc)
{
ASSERT_NE(adapterDescs_, nullptr);
ASSERT_NE(adapterDescs_->ports, nullptr);
for (uint32_t index = 0; index < adapterDescs_->portsLen; index++) {
if (adapterDescs_->ports[index].dir == PORT_OUT) {
devDesc.portId = adapterDescs_->ports[index].portId;
return;
}
}
}
void AudioAdapterBenchmarkTest::SetUp(const ::benchmark::State &state)
{
uint32_t size = g_audioAdapterNumMax;
manager_ = IAudioManagerGet(false);
ASSERT_NE(manager_, nullptr);
adapterDescs_ = (struct AudioAdapterDescriptor *)OsalMemCalloc(
sizeof(struct AudioAdapterDescriptor) * (g_audioAdapterNumMax));
ASSERT_NE(adapterDescs_, nullptr);
ASSERT_EQ(HDF_SUCCESS, manager_->GetAllAdapters(manager_, adapterDescs_, &size));
if (size > g_audioAdapterNumMax) {
ReleaseAdapterDescs(adapterDescs_, g_audioAdapterNumMax);
ASSERT_LT(size, g_audioAdapterNumMax);
}
if (manager_->LoadAdapter(manager_, &adapterDescs_[0], &adapter_) != HDF_SUCCESS) {
ReleaseAdapterDescs(adapterDescs_, g_audioAdapterNumMax);
ASSERT_TRUE(false);
}
if (adapter_ == nullptr) {
ReleaseAdapterDescs(adapterDescs_, g_audioAdapterNumMax);
ASSERT_TRUE(false);
}
}
void AudioAdapterBenchmarkTest::TearDown(const ::benchmark::State &state)
{
ASSERT_NE(manager_, nullptr);
ASSERT_NE(adapter_, nullptr);
manager_->UnloadAdapter(manager_, adapterDescs_[0].adapterName);
ReleaseAdapterDescs(adapterDescs_, g_audioAdapterNumMax);
adapter_ = nullptr;
IAudioManagerRelease(manager_, false);
manager_ = nullptr;
}
BENCHMARK_F(AudioAdapterBenchmarkTest, InitAllPorts)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
for (auto _ : state) {
ret = adapter_->InitAllPorts(adapter_);
EXPECT_EQ(HDF_SUCCESS, ret);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, InitAllPorts)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, CreateRenderAndDestroyRender)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
struct IAudioRender *render = nullptr;
struct AudioDeviceDescriptor devicedesc = {};
struct AudioSampleAttributes attrs = {};
InitDevDesc(devicedesc);
devicedesc.desc = const_cast<char*>("primary");
devicedesc.pins = PIN_OUT_SPEAKER;
InitAttrs(attrs);
attrs.silenceThreshold = 0;
attrs.streamId = 0;
for (auto _ : state) {
ret = adapter_->CreateRender(adapter_, &devicedesc, &attrs, &render, &renderId_);
if (ret != HDF_SUCCESS) {
attrs.format = AUDIO_FORMAT_TYPE_PCM_32_BIT;
ASSERT_EQ(HDF_SUCCESS, adapter_->CreateRender(adapter_, &devicedesc, &attrs, &render, &renderId_));
}
ret = adapter_->DestroyRender(adapter_, renderId_);
EXPECT_EQ(HDF_SUCCESS, ret);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, CreateRenderAndDestroyRender)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, CreateCaptureAndDestroyCapture)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
struct IAudioCapture *capture = nullptr;
struct AudioDeviceDescriptor devicedesc = {};
struct AudioSampleAttributes attrs = {};
InitDevDesc(devicedesc);
devicedesc.desc = const_cast<char*>("primary");
devicedesc.pins = PIN_IN_MIC;
InitAttrs(attrs);
attrs.silenceThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE;
for (auto _ : state) {
ret = adapter_->CreateCapture(adapter_, &devicedesc, &attrs, &capture, &captureId_);
if (ret != HDF_SUCCESS) {
attrs.format = AUDIO_FORMAT_TYPE_PCM_32_BIT;
ASSERT_EQ(HDF_SUCCESS, adapter_->CreateCapture(adapter_, &devicedesc, &attrs, &capture, &captureId_));
}
ret = adapter_->DestroyCapture(adapter_, captureId_);
EXPECT_EQ(HDF_SUCCESS, ret);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, CreateCaptureAndDestroyCapture)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, GetPortCapability)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
struct AudioPort port = {};
struct AudioPortCapability capability = {};
port.dir = PORT_OUT;
port.portId = 0;
port.portName = const_cast<char*>("primary");
for (auto _ : state) {
ret = adapter_->GetPortCapability(adapter_, &port, &capability);
ASSERT_TRUE(ret == HDF_SUCCESS || ret == HDF_ERR_NOT_SUPPORT);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, GetPortCapability)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, SetPassthroughMode)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
struct AudioPort port = {};
port.dir = PORT_OUT;
port.portId = 0;
port.portName = const_cast<char*>("primary");
enum AudioPortPassthroughMode mode = PORT_PASSTHROUGH_LPCM;
for (auto _ : state) {
ret = adapter_->SetPassthroughMode(adapter_, &port, mode);
ASSERT_TRUE(ret == HDF_SUCCESS || ret == HDF_FAILURE);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, SetPassthroughMode)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, GetPassthroughMode)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
struct AudioPort port = {};
port.dir = PORT_OUT;
port.portId = 0;
port.portName = const_cast<char*>("primary");
enum AudioPortPassthroughMode mode;
for (auto _ : state) {
ret = adapter_->GetPassthroughMode(adapter_, &port, &mode);
ASSERT_TRUE(ret == HDF_SUCCESS || ret == HDF_FAILURE);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, GetPassthroughMode)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, GetDeviceStatus)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
struct AudioDeviceStatus status = {};
for (auto _ : state) {
ret = adapter_->GetDeviceStatus(adapter_, &status);
EXPECT_EQ(HDF_SUCCESS, ret);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, GetDeviceStatus)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, GetMicMute)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
bool mute = false;
for (auto _ : state) {
ret = adapter_->GetMicMute(adapter_, &mute);
ASSERT_TRUE(ret == HDF_SUCCESS || ret == HDF_ERR_NOT_SUPPORT);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, GetMicMute)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, SetVoiceVolume)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
float volume = 0;
for (auto _ : state) {
ret = adapter_->SetVoiceVolume(adapter_, volume);
ASSERT_TRUE(ret == HDF_SUCCESS || ret == HDF_ERR_NOT_SUPPORT);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, SetVoiceVolume)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, SetExtraParams)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
enum AudioExtParamKey key = AUDIO_EXT_PARAM_KEY_LOWPOWER;
char condition[AUDIO_ADAPTER_BUF_TEST];
const char *value = "sup_sampling_rates=4800;sup_channels=1;sup_formats=2;";
for (auto _ : state) {
ret = adapter_->SetExtraParams(adapter_, key, condition, value);
ASSERT_TRUE(ret == HDF_SUCCESS || ret == HDF_ERR_NOT_SUPPORT);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, SetExtraParams)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, GetExtraParams)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
enum AudioExtParamKey key = AUDIO_EXT_PARAM_KEY_NONE;
char condition[AUDIO_ADAPTER_BUF_TEST];
char value[AUDIO_ADAPTER_BUF_TEST] = "sup_sampling_rates=4800;sup_channels=1;sup_formats=2;";
uint32_t valueLen = AUDIO_ADAPTER_BUF_TEST;
for (auto _ : state) {
ret = adapter_->GetExtraParams(adapter_, key, condition, value, valueLen);
EXPECT_NE(HDF_SUCCESS, ret);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, GetExtraParams)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, UpdateAudioRoute)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
struct AudioRoute route = {};
int32_t routeHandle = 0;
for (auto _ : state) {
ret = adapter_->UpdateAudioRoute(adapter_, &route, &routeHandle);
EXPECT_NE(HDF_SUCCESS, ret);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, UpdateAudioRoute)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, ReleaseAudioRoute)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
int32_t routeHandle = 0;
for (auto _ : state) {
ret = adapter_->ReleaseAudioRoute(adapter_, routeHandle);
EXPECT_NE(HDF_SUCCESS, ret);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, ReleaseAudioRoute)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, RegExtraParamObserver)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
int8_t cookie = 0;
struct IAudioCallback *audioCallback = nullptr;
for (auto _ : state) {
ret = adapter_->RegExtraParamObserver(adapter_, audioCallback, cookie);
ASSERT_TRUE(ret == HDF_SUCCESS || ret == HDF_ERR_INVALID_PARAM);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, RegExtraParamObserver)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, CreateCallTransfer)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
for (auto _ : state) {
ret = adapter_->CreateCallTransfer(adapter_);
ASSERT_TRUE(ret == HDF_SUCCESS || ret == HDF_ERR_NOT_SUPPORT);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, CreateCallTransfer)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
BENCHMARK_F(AudioAdapterBenchmarkTest, SetPhoneCallScene)(benchmark::State &state)
{
ASSERT_NE(adapter_, nullptr);
int32_t ret;
for (auto _ : state) {
ret = adapter_->SetPhoneCallScene(adapter_, SCENE_TYPE_TRANSFER);
ASSERT_TRUE(ret == HDF_SUCCESS || ret == HDF_ERR_NOT_SUPPORT);
}
}
BENCHMARK_REGISTER_F(AudioAdapterBenchmarkTest, SetPhoneCallScene)->
Iterations(ITERATION_FREQUENCY)->Repetitions(REPETITION_FREQUENCY)->ReportAggregatesOnly();
}