【无标题】

简介: 【无标题】

1、音频服务初始化流程

当前版本:Android 12

大致的创建流程如下:

1.1 开机启动音频服务

音频服务在frameworks/av/media/audioserver/main_audioserver.cpp中,这里会启动音频的AudioFlingerAudioPolicyService两大组件,简单的流程如下:

经过上面流程之后,音频系统中会启动AudioFlinger用于处理后面所有的音频播放,AudioFlinger具体的功能后面再详细分析,AudioPolicyService负责后面的音频策略的处理等流程,AudioFlingerAudioPolicyService之间进行交互

frameworks\av\media\audioserver\main_audioserver.cpp

AudioFlinger::instantiate();
AudioPolicyService::instantiate();

1.2 AudioFlinger模块加载

通过上面流程会调用到AudioFlinger的构造函数,进行AudioFlinger模块的处理,流程如下:

AudioFlinger::AudioFlinger()
    : mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
      mPrimaryHardwareDev(NULL),
      mAudioHwDevs(NULL),
      mHardwareStatus(AUDIO_HW_IDLE),
      mMasterVolume(1.0f),
      mMasterMute(false),
      // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
      mMode(AUDIO_MODE_INVALID),
      mBtNrecIsOff(false),
      mIsLowRamDevice(true),
      mIsDeviceTypeKnown(false),
      mTotalMemory(0),
      mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
      mGlobalEffectEnableTime(0),
      mPatchPanel(this),
      mDeviceEffectManager(this),
      mSystemReady(false)
{
    // Move the audio session unique ID generator start base as time passes to limit risk of
    // generating the same ID again after an audioserver restart.
    // This is important because clients will reuse previously allocated audio session IDs
    // when reconnecting after an audioserver restart and newly allocated IDs may conflict with
    // active clients.
    // Moving the base by 1 for each elapsed second is a good compromise between avoiding overlap
    // between allocation ranges and not reaching wrap around too soon.
    timespec ts{};
    clock_gettime(CLOCK_MONOTONIC, &ts);
    // zero ID has a special meaning, so start allocation at least at AUDIO_UNIQUE_ID_USE_MAX
    uint32_t movingBase = (uint32_t)std::max((long)1, ts.tv_sec);
    // unsigned instead of audio_unique_id_use_t, because ++ operator is unavailable for enum
    for (unsigned use = AUDIO_UNIQUE_ID_USE_UNSPECIFIED; use < AUDIO_UNIQUE_ID_USE_MAX; use++) {
        mNextUniqueIds[use] =
                ((use == AUDIO_UNIQUE_ID_USE_SESSION || use == AUDIO_UNIQUE_ID_USE_CLIENT) ?
                        movingBase : 1) * AUDIO_UNIQUE_ID_USE_MAX;
    }
 
#if 1
    // FIXME See bug 165702394 and bug 168511485
    const bool doLog = false;
#else
    const bool doLog = property_get_bool("ro.test_harness", false);
#endif
    if (doLog) {
        mLogMemoryDealer = new MemoryDealer(kLogMemorySize, "LogWriters",
                MemoryHeapBase::READ_ONLY);
        (void) pthread_once(&sMediaLogOnce, sMediaLogInit);
    }
 
    // reset battery stats.
    // if the audio service has crashed, battery stats could be left
    // in bad state, reset the state upon service start.
    BatteryNotifier::getInstance().noteResetAudio();
 
    mDevicesFactoryHal = DevicesFactoryHalInterface::create();
    mEffectsFactoryHal = EffectsFactoryHalInterface::create();
 
    mMediaLogNotifier->run("MediaLogNotifier");
    std::vector<pid_t> halPids;
    mDevicesFactoryHal->getHalPids(&halPids);
    TimeCheck::setAudioHalPids(halPids);
 
    // Notify that we have started (also called when audioserver service restarts)
    mediametrics::LogItem(mMetricsId)
        .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_CTOR)
        .record();
}
 
void AudioFlinger::onFirstRef()
{
    Mutex::Autolock _l(mLock);
 
    /* TODO: move all this work into an Init() function */
    char val_str[PROPERTY_VALUE_MAX] = { 0 };
    if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
        uint32_t int_val;
        if (1 == sscanf(val_str, "%u", &int_val)) {
            mStandbyTimeInNsecs = milliseconds(int_val);
            ALOGI("Using %u mSec as standby time.", int_val);
        } else {
            mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
            ALOGI("Using default %u mSec as standby time.",
                    (uint32_t)(mStandbyTimeInNsecs / 1000000));
        }
    }
 
    mMode = AUDIO_MODE_NORMAL;
 
    gAudioFlinger = this;  // we are already refcounted, store into atomic pointer.
 
    mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
    mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
}


在上面的构造函数中实例化了设备接口以及音效接口,此时AudioFlinger模块已经成功创建出来,后面AudioPolicyService创建出来后就可以和AudioFlinger之间进行交互了


1.3 AudioPolicyService模块加载

AudioPolicyService负责音频的一些策略管理以及命令处理,具体的启动流程如下:


frameworks\av\services\audiopolicy\service\AudioPolicyService.cpp


AudioPolicyService::AudioPolicyService()
    : BnAudioPolicyService(),
      mAudioPolicyManager(NULL),
      mAudioPolicyClient(NULL),
      mPhoneState(AUDIO_MODE_INVALID),
      mCaptureStateNotifier(false),
      mCreateAudioPolicyManager(createAudioPolicyManager),
      mDestroyAudioPolicyManager(destroyAudioPolicyManager) {
}


mCreateAudioPolicyManager是CreateAudioPolicyManagerInstance类型的实例


using CreateAudioPolicyManagerInstance = AudioPolicyInterface* (*)(AudioPolicyClientInterface*);
using DestroyAudioPolicyManagerInstance = void (*)(AudioPolicyInterface*);


CreateAudioPolicyManagerInstance是一个函数指针指向 createAudioPolicyManager


mDestroyAudioPolicyManager同理


mAudioPolicyManager = mCreateAudioPolicyManager(mAudioPolicyClient);
就相当于
createAudioPolicyManager(mAudioPolicyClient)
void AudioPolicyService::onFirstRef()
{
    {
        Mutex::Autolock _l(mLock);
 
        // start audio commands thread
        mAudioCommandThread = new AudioCommandThread(String8("ApmAudio"), this);
        // start output activity command thread
        mOutputCommandThread = new AudioCommandThread(String8("ApmOutput"), this);
 
        mAudioPolicyClient = new AudioPolicyClient(this);
 
        loadAudioPolicyManager();
        mAudioPolicyManager = mCreateAudioPolicyManager(mAudioPolicyClient);
    }
 
    // load audio processing modules
    sp<AudioPolicyEffects> audioPolicyEffects = new AudioPolicyEffects();
    sp<UidPolicy> uidPolicy = new UidPolicy(this);
    sp<SensorPrivacyPolicy> sensorPrivacyPolicy = new SensorPrivacyPolicy(this);
    {
        Mutex::Autolock _l(mLock);
        mAudioPolicyEffects = audioPolicyEffects;
        mUidPolicy = uidPolicy;
        mSensorPrivacyPolicy = sensorPrivacyPolicy;
    }
 
    // @Rockchip For bootvideo
    char value[PROPERTY_VALUE_MAX];
    property_get("persist.sys.bootvideo.enable", value, "false");
    if (!strcmp(value, "true")) {
        mOutputCommandThread->registerUidCommand(uidPolicy);
        ALOGD("bootvideo enable,delay run Policy registerSelf");
    } else {
        uidPolicy->registerSelf();
        sensorPrivacyPolicy->registerSelf();
    }
    // @end
 
    // Create spatializer if supported
    if (mAudioPolicyManager != nullptr) {
        Mutex::Autolock _l(mLock);
        const audio_attributes_t attr = attributes_initializer(AUDIO_USAGE_MEDIA);
        AudioDeviceTypeAddrVector devices;
        bool hasSpatializer = mAudioPolicyManager->canBeSpatialized(&attr, nullptr, devices);
        if (hasSpatializer) {
            mSpatializer = Spatializer::create(this);
        }
    }
    AudioSystem::audioPolicyReady();
}
1. static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
2. {
3.     AudioPolicyManager *apm = new AudioPolicyManager(clientInterface);
4. status_t status = apm->initialize();
5. if (status != NO_ERROR) {
6. delete apm;
7.         apm = nullptr;
8.     }
9. return apm;
10. }


frameworks\av\services\audiopolicy\managerdefault\AudioPolicyManager.cpp


创建AudioPolicyManager


AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface,
                                       bool /*forTesting*/)
    :
    mUidCached(AID_AUDIOSERVER), // no need to call getuid(), there's only one of us running.
    mpClientInterface(clientInterface),
    mLimitRingtoneVolume(false), mLastVoiceVolume(-1.0f),
    mA2dpSuspended(false),
    mConfig(mHwModulesAll, mOutputDevicesAll, mInputDevicesAll, mDefaultOutputDevice),
    mAudioPortGeneration(1),
    mBeaconMuteRefCount(0),
    mBeaconPlayingRefCount(0),
    mBeaconMuted(false),
    mTtsOutputAvailable(false),
    mMasterMono(false),
    mMusicEffectOutput(AUDIO_IO_HANDLE_NONE)
{
}
 
AudioPolicyManager::AudioPolicyManager(AudioPolicyClientInterface *clientInterface)
        : AudioPolicyManager(clientInterface, false /*forTesting*/)
{
    loadConfig();
}
void AudioPolicyManager::loadConfig() {
    if (deserializeAudioPolicyXmlConfig(getConfig()) != NO_ERROR) {
        ALOGE("could not load audio policy configuration file, setting defaults");
        getConfig().setDefault();
    }
    //TODO: b/193496180 use spatializer flag at audio HAL when available
    getConfig().convertSpatializerFlag();
}
status_t AudioPolicyManager::initialize() {
    {
        auto engLib = EngineLibrary::load(
                        "libaudiopolicyengine" + getConfig().getEngineLibraryNameSuffix() + ".so");
        if (!engLib) {
            ALOGE("%s: Failed to load the engine library", __FUNCTION__);
            return NO_INIT;
        }
        mEngine = engLib->createEngine();
        if (mEngine == nullptr) {
            ALOGE("%s: Failed to instantiate the APM engine", __FUNCTION__);
            return NO_INIT;
        }
    }
    mEngine->setObserver(this);
    status_t status = mEngine->initCheck();
    if (status != NO_ERROR) {
        LOG_FATAL("Policy engine not initialized(err=%d)", status);
        return status;
    }
 
    mCommunnicationStrategy = mEngine->getProductStrategyForAttributes(
        mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL));
 
    // after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;
    // open all output streams needed to access attached devices
    onNewAudioModulesAvailableInt(nullptr /*newDevices*/);
 
    // make sure default device is reachable
    if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
        ALOGE_IF(mDefaultOutputDevice != 0, "Default device %s is unreachable",
                 mDefaultOutputDevice->toString().c_str());
        status = NO_INIT;
    }
    // If microphones address is empty, set it according to device type
    for (size_t i = 0; i < mAvailableInputDevices.size(); i++) {
        if (mAvailableInputDevices[i]->address().empty()) {
            if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BUILTIN_MIC) {
                mAvailableInputDevices[i]->setAddress(AUDIO_BOTTOM_MICROPHONE_ADDRESS);
            } else if (mAvailableInputDevices[i]->type() == AUDIO_DEVICE_IN_BACK_MIC) {
                mAvailableInputDevices[i]->setAddress(AUDIO_BACK_MICROPHONE_ADDRESS);
            }
        }
    }
 
    ALOGW_IF(mPrimaryOutput == nullptr, "The policy configuration does not declare a primary output");
 
    // Silence ALOGV statements
    property_set("log.tag." LOG_TAG, "D");
 
    updateDevicesAndOutputs();
    return status;
}
  • 这里调用的createAudioPolicyManager
  • 解析的配置文件包含audio_policy_configuration.xml,用于解析包含音频策略在内的一些配置文件
  • deserializeAudioPolicyFile方法定义在frameworks/av/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp文件中
  • primary_audio_policy_configuration.xml文件解析流程配置解析
  • Engine配置分析

总结:

  1. 首先分析了从AudioPolicyService创建AudioPolicyManager的流程,这里涉及到第三方自己的AudioPolicyManager,所以中间多了一个AudioPolicyManagerSPRD的创建
  2. 有了AudioPolicyManager对象之后需要加载音频的一些配置文件,包括描述所有外部设备以及设备之间路由情况的primary_audio_policy_configuration.xml,这个xml文件解析之后会将内容存放到AudioPolicyManager持有的AudioPolicyConfig对象中,具体的作用我们后面分析
  3. 加载完xml之后就是进行Engine对象的创建,这个Engine对象负责管理音频策略相关的内容
  4. Engine对象创建完毕之后需要对xml解析出来的内容进行处理,这部分涉及和AudioFlinger的交互,放在后面一节讲述


目录
相关文章
|
4天前
|
IDE Java 持续交付
【无标题】
【无标题】
24 1
|
算法 C++
无标题。。。
无标题。。。
|
前端开发 JavaScript
HTML之<form><textarea>元素详解
一篇了解form和textarea元素
361 0
HTML之<form><textarea>元素详解
|
Web App开发 移动开发 前端开发
HTML5关于contenteditable介绍
HTML5已经从一个新的名词变成了我们在项目中经常用到的东西了,今天我们就来分析一番其中contenteditable 。
154 0
|
应用服务中间件 nginx NoSQL
Title comes here
asdasdadawdwadaw
1445 0
无标题
   OOP是从静态角度考虑程序结构,OOP对业务处理过程中的实体、属性和行为进行抽象的封装以获得更加清晰高效化的逻辑划分。研究的是静态领域。 AOP从动态角度考虑程序运行过程,针对业务处理过程中的切面进行提取,所面对的是业务处理过程中的某个步骤或者阶段,研究的是一种动态的过程。
722 0