audiopolicymanagertest-创建AudioPatch

audiopolicymanagertest TEST_F(…)学习

提要

audiopolicymanagertest.cpp中,使用gtest框架,代码调用RUN_ALL_TESTS()时,TEST_F(…)的主要流程如下:

  • 调用testsuite类SetUp()进行基础的初始化工作。
  • 执行TEST_F代码块中的代码。
  • 调用testsuite类TearDown)进行销毁工作。

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());
}
  • 创建AudioPolicyManagerTestClientAudioPolicyTestManager这两个对象。在创建AudioPolicyTestManager时将之前创建的client注册到里面,创建声音曲线mVolumeCurvesaudioPolicyConfig对象。
    mpClientInterface(clientInterface),
...
    mVolumeCurves(new StreamDescriptorCollection()),
    mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
            mDefaultOutputDevice),
...
  • 设置audiopolicyconfig的默认配置
  1. 创建DeviceDescriptor类型的输入输出设备,mType都为:AUDIO_PORT_TYPE_DEVICE。并将其分别加入到DeviceVector类型的数组中。
  2. 创建名字为"primary"的HwModule模块。
  3. 创建OutputProfile的对象,其中mType为:AUDIO_PORT_TYPE_MIX。并将mModule指向 2. 创建的HwModule模块。
  4. 创建一个AudioProfile对象,并初始化该对象的音频格式通道数采样格式等,最后将创建的AudioProfile对象添加到OutputProfile对象的数组成员中(mProfiles)。
  5. 添加DeviceVector类型的输出设备数组到OutputProfile对象中,并设置输出场景的Flag。
  6. 创建输入场景,并将HwModule与输入场景关联起来,创建音频场景并将其添加到输入场景中,添加默认输入设备数组到输入场景支持的数组中去。
  7. 最后将输入输出场景注册到HwModule中去,将HwModule添加到mHwModules列表中去。
  • AudioPolicyTestManager初始化
  1. 初始化每种流对应策略的音量曲线。
// 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的衰减值)
  1. 创建Engine引擎。
  2. 获取当前有效的输入输出设备类型。
    // 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);
   }
  1. 遍历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()) {
             ...
       }
   }
  1. 遍历HwModule的输出场景。获取OutputProfile中支持的设备类型,创建SwAudioOutputDescriptor实例,并把OutputProfilempClientInterface注册进去。通过mPort获取OutputProfile之前注册的音频格式通道数采样率并分别初始化自己对应的成员变量。之后设置获取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);
      }
 }
  1. 遍历HwModule的输入场景。从InputProfile中找到mAvailableInputDevices支持的设备类型。创建AudioInputDescriptor对象,并将InputProfilempClientInterface注册到该对象的mProfile和mClientInterface中,通过InputProfile获取音频格式通道数采样率分别赋值给mSamplingRate, mChannelMask, mFormat。
    通过当前场景支持的类型profileType查找到支持的输入设备列表。通过输入设备列表获取到address。最后调用open打开输入设备,返回输入设备句柄。
    mAvailableInputDevices中对应的设备与该HwModule关联。并将inputprofile导入到具体的设备中去。最后关闭输入设备。
  2. updateDevicesAndOutputs()
  • 做断言处理
  1. ASSERT_EQ(NO_ERROR, mManager->initCheck()),根据代码断言为真。
status_t AudioPolicyManager::initCheck()
{
   return hasPrimaryOutput() ? NO_ERROR : NO_INIT;
}

TEST_F代码段

  • createAudioPatch参数断言
// 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();
}

你可能感兴趣的:(Android)