audiopolicymanagertest-AudioPatchの作成
11215 ワード
audiopolicymanagertest TEST_F(…)学習
要約
audiopolicymanagertest.cppでgtestフレームワークを使用して、コード呼び出しRUN_ALL_TESTS()の場合、TEST_F(…)の主な流れは以下の通りである.はtestsuiteクラスSetUp()を呼び出してベースの初期化作業を行う. TEST_を実行Fコードブロック内のコード. testsuiteクラスTearDown)を呼び出して破棄作業を行う.
AudioPolicyManagerTest::SetUp()分析
コードは次のとおりです.は、 audiopolicyconfigのデフォルト構成 を設定するは は、「primary」という名前の は、mTypeが は、 入力シーンを作成し、 は最後に、入出力シーンを AudioPolicyTestManager初期化 は、各ストリームに対応するポリシーの音量曲線を初期化する. Engineエンジンを作成します. は、現在有効な入出力デバイスタイプを取得する. は、 HwModuleの出力シーンを巡ります. HwModuleの入力シーンを巡回します. updateDevicesAndOutputs() 断言処理 ASSERT_EQ(NO_ERROR,mManager->initCheck()は,コードによって真と断言する.
TEST_Fコードセグメント createAudioPatchパラメータ断言
AudioPolicyManagerTest::TearDown()分析
要約
audiopolicymanagertest.cppでgtestフレームワークを使用して、コード呼び出しRUN_ALL_TESTS()の場合、TEST_F(…)の主な流れは以下の通りである.
AudioPolicyManagerTest::SetUp()分析
コードは次のとおりです.
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());
}
AudioPolicyManagerTestClient
とAudioPolicyTestManager
の2つのオブジェクトを作成します.AudioPolicyTestManager
を作成すると、前に作成したクライアントが登録され、サウンドカーブmVolumeCurves
とaudioPolicyConfig
のオブジェクトが作成されます. mpClientInterface(clientInterface),
...
mVolumeCurves(new StreamDescriptorCollection()),
mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
mDefaultOutputDevice),
...
DeviceDescriptor
型の入出力デバイスを作成し、mTypeはいずれも:AUDIO_PORT_TYPE_DEVICE
である.DeviceVector
型の配列にそれぞれ加えた.HwModule
モジュールを作成します.OutputProfile
であるAUDIO_PORT_TYPE_MIX
のオブジェクトを作成します.mModuleを2に向ける.作成されたHwModule
モジュール.AudioProfile
オブジェクトを作成し、そのオブジェクトのオーディオフォーマット、チャネル数、サンプリングフォーマットなどを初期化し、最後に作成したAudioProfile
オブジェクトをOutputProfile
オブジェクトの配列メンバーに追加する(mProfiles).DeviceVector
タイプの出力デバイス配列をOutputProfile
オブジェクトに追加し、出力シーンのFlagを設定します.HwModule
を入力シーンに関連付け、オーディオシーンを作成して入力シーンに追加し、デフォルトの入力デバイス配列を入力シーンでサポートされている配列に追加します.HwModule
に登録し、HwModule
をmHwModules
リストに追加する.// VolumeProfiles :
// default volume curves per stream and device category. See initializeVolumeCurves()
static const VolumeCurvePoint *sVolumeProfiles[AUDIO_STREAM_CNT][DEVICE_CATEGORY_CNT];
// :
const VolumeCurvePoint *Gains::sVolumeProfiles[AUDIO_STREAM_CNT]
[DEVICE_CATEGORY_CNT] = {
{ // AUDIO_STREAM_VOICE_CALL
Gains::sDefaultVoiceVolumeCurve, // DEVICE_CATEGORY_HEADSET
Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_SPEAKER
Gains::sSpeakerVoiceVolumeCurve, // DEVICE_CATEGORY_EARPIECE
Gains::sDefaultMediaVolumeCurve, // DEVICE_CATEGORY_EXT_MEDIA
Gains::sHearingAidVolumeCurve // DEVICE_CATEGORY_HEARING_AID
},
...
}
// VolumeCurvePoint :
const VolumeCurvePoint
Gains::sDefaultVoiceVolumeCurve[Volume::VOLCNT] = {
{0, -42.0f}, {33, -28.0f}, {66, -14.0f}, {100, 0.0f}
};
// VolumeCurvePoint ,mIndex( ),mDBAttenuation(DB )
// mAvailableOutputDevices and mAvailableInputDevices now contain all attached devices
// open all output streams needed to access attached devices
audio_devices_t outputDeviceTypes = mAvailableOutputDevices.types();
audio_devices_t inputDeviceTypes = mAvailableInputDevices.types() & ~AUDIO_DEVICE_BIT_IN;
// :
void DeviceVector::refreshTypes()
{
mDeviceTypes = AUDIO_DEVICE_NONE;
for (size_t i = 0; i < size(); i++) {
mDeviceTypes |= itemAt(i)->type();
}
ALOGV("DeviceVector::refreshTypes() mDeviceTypes %08x", mDeviceTypes);
}
mHwModulesAll
を巡回し、各HwModuleオブジェクトを初期化する.まずhwModuleが指定したハードウェアライブラリをロードし、ロードしたハンドルをHwModuleのmHandle
メンバー変数に戻し、次にHwModuleが対応する出力シーンを順次巡回し、出力ストリームを開くなどの操作を行い、最後にHwModuleが対応する入力シーンを巡回し、入力ストリームを開く/閉じるなどの操作を行う. for (const auto& hwModule : mHwModulesAll) {
hwModule->setHandle(mpClientInterface->loadHwModule(hwModule->getName()));
if (hwModule->getHandle() == AUDIO_MODULE_HANDLE_NONE) {
ALOGW("could not open HW module %s", hwModule->getName());
continue;
}
mHwModules.push_back(hwModule);
// open all output streams needed to access attached devices
// except for direct output streams that are only opened when they are actually
// required by an app.
// This also validates mAvailableOutputDevices list
for (const auto& outProfile : hwModule->getOutputProfiles()) {
...
}
// open input streams needed to access attached devices to validate
// mAvailableInputDevices list
for (const auto& inProfile : hwModule->getInputProfiles()) {
...
}
}
OutputProfile
でサポートされているデバイスタイプを取得し、SwAudioOutputDescriptor
インスタンスを作成し、OutputProfile
およびmpClientInterface
を登録します.OutputProfile
以前に登録されたオーディオフォーマット、チャネル数、サンプリングレートをmPortによって取得し、それぞれに対応するメンバー変数を初期化する.その後、OutputProfile
のFlagを取得し、mFlagに設定する.OutputProfile
の構成(デバイス)タイプを取得し、各OutputProfile
はprofileTypeに対応する.サポートされているデバイス配列では、profileTypeによって対応するDeviceDescriptor
デバイス配列を検索し、最初のDeviceDescriptor
のaddressを取得します.SwAudioOutputDescriptor
のopenを呼び出してoutputstreamを開きます.現在のHwModuleをmAvailableOutputDevicesに関連付けて、mAvailableOutputDevices接続ステータスを更新します.SwAudioOutputDescriptor
をmPrimaryOutputに登録します.outputとSwAudioOutputDescriptor
のキー値のペアをmOutputs
に追加します.SwAudioOutputDescriptor
オブジェクトの各ストリームのカーブボリュームを設定します.現在有効な出力をmMusicEffectOutput
に設定します.出力デバイスを設定し、SwAudioOutputDescriptor
オブジェクトのpatchを構成し、mpClientInterface->createAudioPatchを呼び出してpatchを作成し、streamボリュームを適用します.// open all output streams needed to access attached devices
// except for direct output streams that are only opened when they are actually
// required by an app.
// This also validates mAvailableOutputDevices list
for (const auto& outProfile : hwModule->getOutputProfiles()) {
...
audio_devices_t profileType = outProfile->getSupportedDevicesType();
if ((profileType & mDefaultOutputDevice->type()) != AUDIO_DEVICE_NONE) {
profileType = mDefaultOutputDevice->type();
} else {
// chose first device present in profile's SupportedDevices also part of
// outputDeviceTypes
profileType = outProfile->getSupportedDeviceForType(outputDeviceTypes);
}
sp outputDesc = new SwAudioOutputDescriptor(outProfile,
mpClientInterface);
const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
const DeviceVector &devicesForType = supportedDevices.getDevicesFromType(profileType);
String8 address = devicesForType.size() > 0 ? devicesForType.itemAt(0)->mAddress
: String8("");
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
status_t status = outputDesc->open(nullptr, profileType, address,
AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
if (status != NO_ERROR) {
ALOGW("Cannot open output stream for device %08x on hw module %s",
outputDesc->mDevice,
hwModule->getName());
} else {
for (const auto& dev : supportedDevices) {
ssize_t index = mAvailableOutputDevices.indexOf(dev);
// give a valid ID to an attached device once confirmed it is reachable
if (index >= 0 && !mAvailableOutputDevices[index]->isAttached()) {
mAvailableOutputDevices[index]->attach(hwModule);
}
}
if (mPrimaryOutput == 0 &&
outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
mPrimaryOutput = outputDesc;
}
addOutput(output, outputDesc);
setOutputDevice(outputDesc,
profileType,
true,
0,
NULL,
address);
}
}
InputProfile
から、mAvailableInputDevices
がサポートするデバイスタイプが見つかりました.AudioInputDescriptor
オブジェクトを作成し、InputProfile
およびmpClientInterface
をそのオブジェクトのmProfileおよびmClientInterfaceに登録し、InputProfile
によってオーディオフォーマット、チャネル数、サンプリングレートをmSamplingRate、mChannelMask、mFormatにそれぞれ割り当てます.サポートされている入力デバイスのリストは、現在のシーンでサポートされているタイプprofileType
によって検索される.デバイスリストを入力してaddressを取得します.最後にopenを呼び出して入力デバイスを開き、入力デバイスハンドルに戻ります.mAvailableInputDevices
の対応するデバイスをHwModuleに関連付ける.inputprofile
を特定のデバイスに導入します.最後に入力デバイスを閉じます.status_t AudioPolicyManager::initCheck()
{
return hasPrimaryOutput() ? NO_ERROR : NO_INIT;
}
TEST_Fコードセグメント
// patch
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(nullptr, &handle, 0));
// handle
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, nullptr, 0));
// patch num_sources==0
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0));
// patch num_source 1
patch.num_sources = AUDIO_PATCH_PORTS_MAX + 1;
patch.num_sinks = 1;
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0));
// patch num_sinks 16
patch.num_sources = 1;
patch.num_sinks = AUDIO_PATCH_PORTS_MAX + 1;
ASSERT_EQ(BAD_VALUE, mManager->createAudioPatch(&patch, &handle, 0))
patch num_source 1
patch.num_sources = 2;
patch.num_sinks = 1;
ASSERT_EQ(INVALID_OPERATION, mManager->createAudioPatch(&patch, &handle, 0));
//patch sources[0].role AUDIO_PORT_ROLE_SINK
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 sinks[0].role AUDIO_PORT_ROLE_SOURCE
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());
AudioPolicyManagerTest::TearDown()分析
void AudioPolicyManagerTest::TearDown() {
mManager.reset();
mClient.reset();
}