audiopolicymanagertest之TEST(AudioPolicyManagerTestInit, Failure)

代碼段一覽

TEST(AudioPolicyManagerTestInit, Failure) {
    AudioPolicyTestClient client;
    AudioPolicyTestManager manager(&client);
    manager.getConfig().setDefault();
    // Since the default client fails to open anything,
    // APM should indicate that the initialization didn't succeed.
    ASSERT_EQ(NO_INIT, manager.initialize());
    ASSERT_EQ(NO_INIT, manager.initCheck());
}

流程分析

根據gtest框架,test代碼最終會執行上面的代碼塊中的內容。

  • 首先創建一個AudioPolicyTestClient對象
  1. AudioPolicyTestClient派生於AudioPolicyClientInterface。是AudioPolicy與AudioFlinger通信的客戶端。
  2. AudioPolicyClientInterface提供了關於硬件的一些操作方法。比如一些常用的接口loadHwModuleopenOutputopenInputgetParameterssetParameters等。
  • 創建AudioPolicyTestManager對象
  1. AudioPolicyTestManager派生於AudioPolicyManager。而AudioPolicyManager繼承於AudioPolicyInterfaceAudioPolicyInterface提供了對音頻流的管理接口。
  2. AudioPolicyInterface提供了對於音頻流控制和策略選擇的操作方法,比如getStrategystartOutputgetOutputForAttr等。所以AudioPolicyManager提供了音頻策略和設備管理,以及音頻流控制的功能。
  3. AudioPolicyTestManager的定義如下:
  class AudioPolicyTestManager : public AudioPolicyManager {
  public:
    explicit AudioPolicyTestManager(AudioPolicyClientInterface *clientInterface)
            : AudioPolicyManager(clientInterface, true /*forTesting*/) { }
    using AudioPolicyManager::getConfig;
    using AudioPolicyManager::initialize;
};

實例化AudiopolicyManager對象,則會調用父類的AudioPolicyManager(clientInterface, true)構造函數,在父類的構造函數中會將AudioPolicyTestClient的實例註冊到mpClientInterface。創建StreamDescriptorCollection/VolumeCurvesCollection對象,該對象註冊到mVolumeCurves,mVolumeCurves包含一個mVector,mVector保存着流id:StreamDescriptor。創建AudioPolicyConfig對象註冊到mConfig。代碼如下:

AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface,
                                       bool /*forTesting*/)
    :
    mUidCached(getuid()),
    mpClientInterface(clientInterface),
    mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
    mA2dpSuspended(false),
#ifdef USE_XML_AUDIO_POLICY_CONF
    mVolumeCurves(new VolumeCurvesCollection()),
    mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
            mDefaultOutputDevice, static_cast<VolumeCurvesCollection*>(mVolumeCurves.get())),
#else
    mVolumeCurves(new StreamDescriptorCollection()),
    mConfig(mHwModulesAll, mAvailableOutputDevices, mAvailableInputDevices,
            mDefaultOutputDevice),
#endif
    mAudioPortGeneration(1),
    mBeaconMuteRefCount(0),
    mBeaconPlayingRefCount(0),
    mBeaconMuted(false),
    mTtsOutputAvailable(false),
    mMasterMono(false),
    mMusicEffectOutput(AUDIO_IO_HANDLE_NONE),
    mHasComputedSoundTriggerSupportsConcurrentCapture(false)
{
}
  • AudioPolicyTestManager設置配置
  1. 通過調用setDefault來對AudioPolicyTestManager實例設置配置,具體代碼如下:
manager.getConfig().setDefault()

最終會調用AudioPolicyConfig中的setDefault()方法。

    void setDefault(void)
    {
        mDefaultOutputDevices = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER);
        sp<HwModule> module;
        sp<DeviceDescriptor> defaultInputDevice = new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC);
        mAvailableOutputDevices.add(mDefaultOutputDevices);
        mAvailableInputDevices.add(defaultInputDevice);

        module = new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY);

        sp<OutputProfile> outProfile;
        outProfile = new OutputProfile(String8("primary"));
        outProfile->attach(module);
        outProfile->addAudioProfile(
                new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100));
        outProfile->addSupportedDevice(mDefaultOutputDevices);
        outProfile->setFlags(AUDIO_OUTPUT_FLAG_PRIMARY);
        module->addOutputProfile(outProfile);

        sp<InputProfile> inProfile;
        inProfile = new InputProfile(String8("primary"));
        inProfile->attach(module);
        inProfile->addAudioProfile(
                new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000));
        inProfile->addSupportedDevice(defaultInputDevice);
        module->addInputProfile(inProfile);

        mHwModules.add(module);
    }
  1. setDefault流程分析
    首先通過new DeviceDescriptor(AUDIO_DEVICE_OUT_SPEAKER)創建一個mDefaultOutputDevices對象。通過new DeviceDescriptor(AUDIO_DEVICE_IN_BUILTIN_MIC)創建一個defaultInputDevice對象。最終將mDefaultOutputDevicesdefaultInputDevice分別註冊mAvailableOutputDevicesmAvailableInputDevices鏈表中。
    接着通過new HwModule(AUDIO_HARDWARE_MODULE_ID_PRIMARY)創建一個硬件模塊module
    通過new OutputProfile(String8("primary"))創建一個輸出配置outProfile,給輸出配置添加一個new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, 44100)對象,並將之前創建的SPEAK設備添加到outProfile中,最後在硬件模塊module中添加outProfile
    通過new InputProfile(String8("primary"))創建一個輸入配置inProfile,給輸入配置添加一個 new AudioProfile(AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_MONO, 8000)對象,並將之前創建的MIC設備添加到InputProfile中,最後在硬件模塊module中添加InputProfile
    最後,將module註冊到mHwModules中。
  • managerinitializeinitCheck進行斷言。
    具體代碼如下:
    ASSERT_EQ(NO_INIT, manager.initialize());
    ASSERT_EQ(NO_INIT, manager.initCheck());
  1. 調用initializeVolumeCurves來進行每一個流的StreamDescriptor策略初始化。如果該Speaker有DRC1功能,則使用默認的VolumeCurvePoint。
  2. 創建Engine引擎實例,並返回引擎實例。Engine代碼如下:
Engine::Engine()
    : mManagerInterface(this),
      mPhoneState(AUDIO_MODE_NORMAL),
      mApmObserver(NULL)
{
    for (int i = 0; i < AUDIO_POLICY_FORCE_USE_CNT; i++) {
        mForceUse[i] = AUDIO_POLICY_FORCE_NONE;
    }
}
  1. AudioPolicyManager註冊到Engine實例中,並做觀察者檢測。
    mEngine->setObserver(this);
    status_t status = mEngine->initCheck();
    if (status != NO_ERROR) {
        LOG_FATAL("Policy engine not initialized(err=%d)", status);
        return status;
    }
  1. 加載硬件庫,並將其返回句柄添加到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;
        }
        ...
}

默認會調用AudioPolicyClient中的loadHwModule方法,但是測試類重新了此方法。具體代碼如下:

//默認方法
audio_module_handle_t AudioPolicyService::AudioPolicyClient::loadHwModule(const char *name)
{
    sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
    if (af == 0) {
        ALOGW("%s: could not get AudioFlinger", __func__);
        return AUDIO_MODULE_HANDLE_NONE;
    }

    return af->loadHwModule(name);
}

//AudioPolicyTestClient重新的方法
    audio_module_handle_t loadHwModule(const char* /*name*/) override {
        return AUDIO_MODULE_HANDLE_NONE;
    }

如果返回參數爲AUDIO_MODULE_HANDLE_NONE則不調用後面的操作,最終退出循環。
5. 將無效的輸入輸出從mAvailableOutputDevicesmAvailableInputDevices列表中移除,並返回NO_INIT,初始化斷言成功。
6. 調用AudioPolicyManager::initCheck()來進行初始化檢查。代碼如下:

status_t AudioPolicyManager::initCheck()
{
    return hasPrimaryOutput() ? NO_ERROR : NO_INIT;
}
  1. for循環沒有執行,就沒有創建輸出,故mPrimaryOutput爲0。

  1. Dynamic Range Control(動態範圍控制)提供聲音壓縮和放大能力,使聲音聽起來更柔和或更大聲,即一種信號調幅方式。 ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章