AudioFlinger与AudioPoliceManager初始化流程

AF/APF启动流程

在启动AudioSeriver服务的过程中会对启动AF/APF。main_audioserver.cpp有如下代码:

cpp 复制代码
    AudioFlinger::instantiate();
    AudioPolicyService::instantiate();

AF初始化流程

1.AudioFlinger::instantiate()

1.1 AudioFlinger构造函数

cpp 复制代码
void AudioFlinger::instantiate() {
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME),
                   new AudioFlingerServerAdapter(new AudioFlinger()), false,
                   IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
}

创建AudioFlingerServerAdapter对象,然后将AudioFlinger对象传入在AudioFlingerr中会调用onFirstRef()函数。

cpp 复制代码
AudioFlinger::AudioFlinger() {
    mDevicesFactoryHal = DevicesFactoryHalInterface::create();
    mEffectsFactoryHal = EffectsFactoryHalInterface::create();
}

在AudioFlinger的构造函数中会创建DevicesFactoryHalInterface和EffectsFactoryHalInterface对象,DevicesFactoryHalInterface对象会调用HIDL的getDevicesFactory()函数,EffectsFactoryHalInterface对象会调用HIDL的getEffectsFactory()函数。
DevicesFactoryHalInterface.h

cpp 复制代码
sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
    return createPreferredImpl<DevicesFactoryHalInterface>(
            "android.hardware.audio", "IDevicesFactory");
}

FactoryHalHidl.h

cpp 复制代码
template <class Interface>
static sp<Interface> createPreferredImpl(const std::string& package, const std::string& interface) {
    return sp<Interface>{static_cast<Interface*>(detail::createPreferredImpl(package, interface))};
}
void* createPreferredImpl(const std::string& package, const std::string& interface) {
    for (auto version = detail::sAudioHALVersions; version != nullptr; ++version) {
        void* rawInterface = nullptr;
        if (hasHalService(package, *version, interface)
                && createHalService(*version, interface, &rawInterface)) {
            return rawInterface;
        }
    }
    return nullptr;
}
const char* sAudioHALVersions[] = {
    "7.0",
    "6.0",
    "5.0",
    "4.0",
    nullptr
};

函数hasHalService功能为将"android.hardware.audio"与sAudioHALVersions拼接从7.0开始循环,从serviceManager中查找是否存在当前的服务比如[email protected]::IDevicesFactory当查到有相关的hidl接口那么就调用函数createHalService
createHalService功能如下:

1.拼接libName ="libaudiohal@"+7.0+".so" factoryFunctionName = "create"+IDevicesFactory

2.dlopen打开库[email protected]"

3.dlsym获取函数createIDevicesFactory

4.调用函数createIDevicesFactory

5.返回rawInterface

6.将rawInterface强转成IDevicesFactory类型
DevicesFactoryHalHybrid.cpp

cpp 复制代码
extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {
    auto service = hardware::audio::CPP_VERSION::IDevicesFactory::getService();
    return service ? new CPP_VERSION::DevicesFactoryHalHybrid(service) : nullptr;
}
DevicesFactoryHalHybrid::DevicesFactoryHalHybrid(sp<IDevicesFactory> hidlFactory)
        : mLocalFactory(new DevicesFactoryHalLocal()),
          mHidlFactory(new DevicesFactoryHalHidl(hidlFactory)) {
}

函数DevicesFactoryHalHybrid功能如下:

1.创建DevicesFactoryHalLocal对象

2.创建DevicesFactoryHalHidl对象

3.将DevicesFactoryHalHidl对象传入DevicesFactoryHalLocal对象

1.2 AudioFlinger::onFirstRef解析

cpp 复制代码
void AudioFlinger::onFirstRef()
{
 mMode = AUDIO_MODE_NORMAL;

    gAudioFlinger = this;  // we are already refcounted, store into atomic pointer.

    mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
    mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
}

1.3总结

main_audioserver.cpp AudioFlinger AudioFlingerServerAdapter DevicesFactoryHalInterface EffectsFactoryHalInterface FactoryHalHidl.h DevicesFactoryHalHybrid.cpp main_audioserver.cpp 创建AudioFlingerServerAdapter 创建AudioFlinger对象 创建DevicesFactoryHalInterface 创建EffectsFactoryHalInterface 调用createPreferredImpl 遍历HAL版本 (7.0->>4.0) 检查hasHalService? 加载[email protected] 获取createIDevicesFactory函数 调用createIDevicesFactory 创建DevicesFactoryHalHybrid 创建DevicesFactoryHalLocal 创建DevicesFactoryHalHidl 返回nullptr,尝试下一个版本 alt [服务存在] [服务不存在] loop [每个HAL版本] 所有版本尝试完毕,创建失败,返回nullptr main_audioserver.cpp AudioFlinger AudioFlingerServerAdapter DevicesFactoryHalInterface EffectsFactoryHalInterface FactoryHalHidl.h DevicesFactoryHalHybrid.cpp

  • 启动入口:

    在AudioServer启动时,通过AudioFlinger::instantiate()和AudioPolicyService::instantiate()初始化AF和APF

    AudioFlinger初始化流程:

  • 创建AudioFlingerServerAdapter,并传入AudioFlinger对象

    在AudioFlinger构造函数中创建两个关键对象:

    DevicesFactoryHalInterface:用于设备工厂

    EffectsFactoryHalInterface:用于音效工厂

  • HAL层交互:

    通过createPreferredImpl函数查找合适的HAL版本(从7.0到4.0)[email protected]

    使用hasHalService检查服务是否存在

    通过createHalService加载对应的.so库并获取工厂函数

  • 设备工厂创建:

    最终创建DevicesFactoryHalHybrid对象

    该对象包含两个子工厂:

    DevicesFactoryHalLocal:本地工厂

    DevicesFactoryHalHidl:HIDL接口工厂

APM初始化流程

1.AudioPolicyService::instantiate()

cpp 复制代码
AudioPolicyService::AudioPolicyService()
    : BnAudioPolicyService(),
      mAudioPolicyManager(NULL),
      mAudioPolicyClient(NULL),
      mPhoneState(AUDIO_MODE_INVALID),
      mCaptureStateNotifier(false),
      mCreateAudioPolicyManager(createAudioPolicyManager),
      mDestroyAudioPolicyManager(destroyAudioPolicyManager) {
}
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;
    }
#ifdef ESWIN_AOSP_ENHANCEMENT
    std::thread notifier([=]() {
        ALOGI("onFirstRef registerSelf start.");
        uidPolicy->registerSelf();
        sensorPrivacyPolicy->registerSelf();
        ALOGI("onFirstRef registerSelf end.");
    });
    notifier.detach();
#endif /* ESWIN_AOSP_ENHANCEMENT */
}

1.1 createAudioPolicyManager

cpp 复制代码
static AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface)
{
    AudioPolicyManager *apm = new AudioPolicyManager(clientInterface);
    status_t status = apm->initialize();
    if (status != NO_ERROR) {
        delete apm;
        apm = nullptr;
    }
    return apm;
}

在函数createAudioPolicyManager中首先会调用AudioPolicyManager的构造函数,在构造函数中调用loadConfig这个函数的作用是解析audio_policy_configuration.xml。我们之后在分析,只需要知道之后时候xml解析结束。 然后调用initialize

1.1.1 AudioPolicyManager::initialize()

cpp 复制代码
status_t AudioPolicyManager::initialize() {
    ···
    onNewAudioModulesAvailableInt(nullptr /*newDevices*/);
    updateDevicesAndOutputs();
    ···
    return status;
}

1.1.2 AudioPolicyManager::onNewAudioModulesAvailableInt()

这个函数很重要 做了很多工作

cpp 复制代码
void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
{
    //mHwModulesAll是xml文件中所有的mudule,mHwModules是已经加载的module
    for (const auto& hwModule : mHwModulesAll) {
        if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
            continue;
        }
        //加载module
        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()) {
            if (!outProfile->canOpenNewIo()) {
                ALOGE("Invalid Output profile max open count %u for profile %s",
                      outProfile->maxOpenCount, outProfile->getTagName().c_str());
                continue;
            }else {
                 ALOGE("valid Output profile max open count %u for profile %s",
                      outProfile->maxOpenCount, outProfile->getTagName().c_str());
            }
            //hasSupportedDevices 都是 xml文件中可以根据route将device跟mixport配对上的
            if (!outProfile->hasSupportedDevices()) {
                ALOGW("Output profile contains no device on module %s", hwModule->getName());
                continue;
            }
            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_TTS) != 0) {
                mTtsOutputAvailable = true;
            }

            const DeviceVector &supportedDevices = outProfile->getSupportedDevices();
            DeviceVector availProfileDevices = supportedDevices.filter(mOutputDevicesAll);
            sp<DeviceDescriptor> supportedDevice = 0;
            // 保存defaultOutputDevice标签内名字和devicePort标签的tagName相同,如Speaker
            if (supportedDevices.contains(mDefaultOutputDevice)) {
                supportedDevice = mDefaultOutputDevice;
            } else {
                // choose first device present in profile's SupportedDevices also part of
                // mAvailableOutputDevices.
                if (availProfileDevices.isEmpty()) {
                    continue;
                }
                supportedDevice = availProfileDevices.itemAt(0);
            }
            //mOutputDevicesAll对应xml中的attachedDevices
            if (!mOutputDevicesAll.contains(supportedDevice)) {
                continue;
            }
            //经过重重过滤其实只剩下speaker
            sp<SwAudioOutputDescriptor> outputDesc = new SwAudioOutputDescriptor(outProfile,
                                                                                 mpClientInterface);
            audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
            //打开通路
            status_t status = outputDesc->open(nullptr, DeviceVector(supportedDevice),
                                               AUDIO_STREAM_DEFAULT,
                                               AUDIO_OUTPUT_FLAG_NONE, &output);
            if (status != NO_ERROR) {
                ALOGW("Cannot open output stream for devices %s on hw module %s",
                      supportedDevice->toString().c_str(), hwModule->getName());
                continue;
            } else{
                  ALOGE(" open output stream for devices %s on hw module %s",
                      supportedDevice->toString().c_str(), hwModule->getName());
            }
            for (const auto &device : availProfileDevices) {
                // give a valid ID to an attached device once confirmed it is reachable
                if (!device->isAttached()) {
                    device->attach(hwModule);
                    mAvailableOutputDevices.add(device);
                    device->setEncapsulationInfoFromHal(mpClientInterface);
                    if (newDevices) newDevices->add(device);
                    setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
                }
            }
            if (mPrimaryOutput == nullptr &&
                    outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
                mPrimaryOutput = outputDesc;
            }
            if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
                outputDesc->close();
            } else {
                addOutput(output, outputDesc);
                setOutputDevices(outputDesc,
                                 DeviceVector(supportedDevice),
                                 true,
                                 0,
                                 NULL);
            }
        }
        // open input streams needed to access attached devices to validate
        // mAvailableInputDevices list
        ···
    }
}

我们来总结一下onNewAudioModulesAvailableInt的功能:

  1. 遍历所有硬件模块(mHwModulesAll),检查是否已加载。
  2. 从hwmodel中找到符合要求的outProfile,这一过程涉及四个变量
    • outProfile 这个变量是mixport
    • supportedDevice xml文件中可以根据route将device跟mixport配对上的
    • defaultOutputDevice xml中defaultOutputDevice对应的device
    • mOutputDevicesAll 对应xml中的attachedDevices
  3. 遍历所有module下面的所有的outProfile,根据OutProfile找到支持的device,返回一个supportDevices ;
  4. 通过mOutputDevicesAll(xml文件中的attrachDevices)过滤出有效的availProfileDevices;
  5. 判断包不包含默认设备mDefaultOutputDevice(xml文件中的defaultOutputDevice),如果包含,设置为默认设备;如果不包含,就设置为第一个设备。
  6. 只设置支持当前输出设备的stream
    接下来我们分别loadHwModuleopen

1.1.3 AudioPolicyManager::loadHwModule

loadHwModule会调用到AudioFlinger中的loadHwModule

cpp 复制代码
audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
{
    Mutex::Autolock _l(mLock);
    AutoMutex lock(mHardwareLock);
    return loadHwModule_l(name);
}
audio_module_handle_t AudioFlinger::loadHwModule_l(const char *name)
{
    for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
        if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
            ALOGW("loadHwModule() module %s already loaded", name);
            return mAudioHwDevs.keyAt(i);
        }
    }

    sp<DeviceHalInterface> dev;

    int rc = mDevicesFactoryHal->openDevice(name, &dev);
    ····
     AudioHwDevice *audioDevice = new AudioHwDevice(handle, name, dev, flags);
    if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_PRIMARY) == 0) {
        mPrimaryHardwareDev = audioDevice;
        mHardwareStatus = AUDIO_HW_SET_MODE;
        mPrimaryHardwareDev->hwDevice()->setMode(mMode);
        mHardwareStatus = AUDIO_HW_IDLE;
    }

    mAudioHwDevs.add(handle, audioDevice);

}

DevicesFactoryHalHybrid::openDevice

cpp 复制代码
status_t DevicesFactoryHalHybrid::openDevice(const char *name, sp<DeviceHalInterface> *device) {
    if (mHidlFactory != 0 && strcmp(AUDIO_HARDWARE_MODULE_ID_A2DP, name) != 0 &&
        strcmp(AUDIO_HARDWARE_MODULE_ID_HEARING_AID, name) != 0) {
        return mHidlFactory->openDevice(name, device);
    }
    return mLocalFactory->openDevice(name, device);
}

这里要注意如果是A2DP就走本地的,如果不是走HIDL的。这里我们是speaker所以走mHidlFactory

cpp 复制代码
status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
    auto factories = copyDeviceFactories();
    if (factories.empty()) return NO_INIT;
    status_t status;
    auto hidlId = idFromHal(name, &status);
    if (status != OK) return status;
    Result retval = Result::NOT_INITIALIZED;
    for (const auto& factory : factories) {
        Return<void> ret = factory->openDevice(
                hidlId,
                [&](Result r, const sp<IDevice>& result) {
                    retval = r;
                    if (retval == Result::OK) {
                        *device = new DeviceHalHidl(result);
                    }
                });
    }
    return BAD_VALUE;
}

DevicesFactory::openDevice

cpp 复制代码
Return<void> DevicesFactory::openDevice(const hidl_string& moduleName, openDevice_cb _hidl_cb) {
    if (moduleName == AUDIO_HARDWARE_MODULE_ID_PRIMARY) {
        return openDevice<PrimaryDevice>(moduleName.c_str(), _hidl_cb);
    }
    return openDevice(moduleName.c_str(), _hidl_cb);
}

解析来的流程如图所示

1.1.4 AudioFlinger::loadHwModule总结

通过传参hwModule->getName(),如primary,通过拼接查询找到合适的audio.primary.xxx.so。,通过dlopen加载so,dlsym获取对应的对象,通过回调将对象返回。最后为AudioFlinger::loadHwModule_l中 sp dev赋值

1.2.1 SwAudioOutputDescriptor::open

cpp 复制代码
status_t SwAudioOutputDescriptor::open(const audio_config_t *config,
                                       const DeviceVector &devices,
                                       audio_stream_type_t stream,
                                       audio_output_flags_t flags,
                                       audio_io_handle_t *output)
{
    ···
        status_t status = mClientInterface->openOutput(mProfile->getModuleHandle(),
                                                   output,
                                                   &lConfig,
                                                   device,
                                                   &mLatency,
                                                   mFlags);
  ····
}

status_t AudioFlinger::openOutput(const media::OpenOutputRequest& request,
                                media::OpenOutputResponse* response)
{
    audio_io_handle_t output;
    ···
    sp<ThreadBase> thread = openOutput_l(module, &output, &config, deviceType, address, flags);
    if (thread != 0) {
        if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
            latencyMs = playbackThread->latency();

            // notify client processes of the new output creation
            playbackThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);

            // the first primary output opened designates the primary hw device if no HW module
            // named "primary" was already loaded.
            AutoMutex lock(mHardwareLock);
            if ((mPrimaryHardwareDev == nullptr) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
                ALOGI("Using module %d as the primary audio interface", module);.
                mPrimaryHardwareDev = playbackThread->getOutput()->audioHwDev;

                mHardwareStatus = AUDIO_HW_SET_MODE;
                mPrimaryHardwareDev->hwDevice()->setMode(mMode);
                mHardwareStatus = AUDIO_HW_IDLE;
            }
        } else {
            MmapThread *mmapThread = (MmapThread *)thread.get();
            mmapThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
        }
        response->output = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
        response->config = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_config_t_AudioConfig(config));
        response->latencyMs = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(latencyMs));
        response->flags = VALUE_OR_RETURN_STATUS(
                legacy2aidl_audio_output_flags_t_int32_t_mask(flags));
        return NO_ERROR;
    }
    }

sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
                                                        audio_io_handle_t *output,
                                                        audio_config_t *config,
                                                        audio_devices_t deviceType,
                                                        const String8& address,
                                                        audio_output_flags_t flags)
{
    //获取合适的AudioHwDevice,这个AudioHwDevice是在loadHwModule_l中创建的
    AudioHwDevice *outHwDev = findSuitableHwDev_l(module, deviceType);
    if (outHwDev == NULL) {
        return 0;
    }

    if (*output == AUDIO_IO_HANDLE_NONE) {
        *output = nextUniqueId(AUDIO_UNIQUE_ID_USE_OUTPUT);
    } else {
        // Audio Policy does not currently request a specific output handle.
        // If this is ever needed, see openInput_l() for example code.
        ALOGE("openOutput_l requested output handle %d is not AUDIO_IO_HANDLE_NONE", *output);
        return 0;
    }

    mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;

···
    AudioStreamOut *outputStream = NULL;
    status_t status = outHwDev->openOutputStream(
            &outputStream,
            *output,
            deviceType,
            flags,
            config,
            address.string());
    mHardwareStatus = AUDIO_HW_IDLE;
    if (status == NO_ERROR) {
        if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
            sp<MmapPlaybackThread> thread =
                    new MmapPlaybackThread(this, *output, outHwDev, outputStream, mSystemReady);
            mMmapThreads.add(*output, thread);
            ALOGD("openOutput_l() created mmap playback thread: ID %d thread %p",
                  *output, thread.get());
            return thread;
        } else {
            sp<PlaybackThread> thread;
            if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
                thread = new OffloadThread(this, outputStream, *output, mSystemReady);
                ALOGD("openOutput_l() created offload output: ID %d thread %p",
                      *output, thread.get());
            } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
                    || !isValidPcmSinkFormat(config->format)
                    || !isValidPcmSinkChannelMask(config->channel_mask)) {
                thread = new DirectOutputThread(this, outputStream, *output, mSystemReady);
                ALOGD("openOutput_l() created direct output: ID %d thread %p",
                      *output, thread.get());
            } else {
                 //创建线程并且key是output
                thread = new MixerThread(this, outputStream, *output, mSystemReady);
                ALOGD("openOutput_l() created mixer output: ID %d thread %p",
                      *output, thread.get());
            }
           
            mPlaybackThreads.add(*output, thread);
            struct audio_patch patch;
            mPatchPanel.notifyStreamOpened(outHwDev, *output, &patch);
            if (thread->isMsdDevice()) {
                thread->setDownStreamPatch(&patch);
            }
            return thread;
        }
    }

    return 0;
}

1.2.2 openOutputStream解析

cpp 复制代码
status_t AudioHwDevice::openOutputStream(
        AudioStreamOut **ppStreamOut,
        audio_io_handle_t handle,
        audio_devices_t deviceType,
        audio_output_flags_t flags,
        struct audio_config *config,
        const char *address)
{
    struct audio_config originalConfig = *config;
    AudioStreamOut *outputStream = new AudioStreamOut(this, flags);
    status_t status = outputStream->open(handle, deviceType, config, address);
    ···
    *ppStreamOut = outputStream;
    return status;
}

status_t AudioStreamOut::open(
        audio_io_handle_t handle,
        audio_devices_t deviceType,
        struct audio_config *config,
        const char *address)
{
    sp<StreamOutHalInterface> outStream;

    audio_output_flags_t customFlags = (config->format == AUDIO_FORMAT_IEC61937)
                ? (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)
                : flags;

    int status = hwDev()->openOutputStream(
            handle,
            deviceType,
            customFlags,
            config,
            address,
            &outStream);

    if (status == NO_ERROR) {
        stream = outStream;
        mHalFormatHasProportionalFrames = audio_has_proportional_frames(config->format);
        status = stream->getFrameSize(&mHalFrameSize);
        LOG_ALWAYS_FATAL_IF(status != OK, "Error retrieving frame size from HAL: %d", status);
        LOG_ALWAYS_FATAL_IF(mHalFrameSize <= 0, "Error frame size was %zu but must be greater than"
                " zero", mHalFrameSize);

    }
    return status;
}

status_t DeviceHalHidl::openOutputStream(
        audio_io_handle_t handle,
        audio_devices_t deviceType,
        audio_output_flags_t flags,
        struct audio_config *config,
        const char *address,
        sp<StreamOutHalInterface> *outStream) {

    Return<void> ret = mDevice->openOutputStream(
            handle, hidlDevice, hidlConfig, hidlFlags,
#if MAJOR_VERSION >= 4
            {} /* metadata */,
#endif
            [&](Result r, const sp<IStreamOut>& result, const AudioConfig& suggestedConfig) {
                retval = r;
                if (retval == Result::OK) {
                    *outStream = new StreamOutHalHidl(result);
                }
                HidlUtils::audioConfigToHal(suggestedConfig, config);
            });
    return processReturn("openOutputStream", ret, retval);
}

最终会调用到audio_hw.c中的函数adev_open_output_stream

cpp 复制代码
static int adev_open_output_stream(struct audio_hw_device *dev,
                                   audio_io_handle_t handle,
                                   audio_devices_t devices,
                                   audio_output_flags_t flags,
                                   struct audio_config *config,
                                   struct audio_stream_out **stream_out,
                                   const char *address __unused) {

    *stream_out = NULL;
    struct esw_stream_out *out
        = (struct esw_stream_out *)calloc(1, sizeof(struct esw_stream_out));
    if (!out) {
        return -ENOMEM;
    }
    out->stream.common.get_sample_rate = out_get_sample_rate;
    out->stream.common.set_sample_rate = out_set_sample_rate;
    out->stream.common.get_buffer_size = out_get_buffer_size;
    out->stream.common.get_channels = out_get_channels;
    out->stream.common.get_format = out_get_format;
    out->stream.common.set_format = out_set_format;
    out->stream.common.standby = out_standby;
    out->stream.common.dump = out_dump;
    out->stream.common.set_parameters = out_set_parameters;
    out->stream.common.get_parameters = out_get_parameters;
    out->stream.common.add_audio_effect = out_add_audio_effect;
    out->stream.common.remove_audio_effect = out_remove_audio_effect;
    out->stream.get_latency = out_get_latency;
    out->stream.set_volume = out_set_volume;
    out->stream.write = out_write;
    out->stream.get_render_position = out_get_render_position;
    out->stream.pause = out_pause;
    out->stream.resume = out_resume;
    out->stream.drain = out_drain;
    out->stream.flush = out_flush;
    out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
    out->sample_rate = config->sample_rate;
    out->paused = false;
···
}

到此我们已经已经打开了一个输出通道,音频数据流从这个通道流向某个设备,这个通道支持的sample_rate、format、channel是从xml解析出来的。

AudioOutputDescriptor构造函数中调用PolicyAudioPort::pickChannelMask解析上述参数规则如下:

对于采样格式,精度越高优先级越高;对于通道掩码(通道数),如果是直接输出 (Direct Output),则通道数越小优先级越高,否则,通道数越大优先级越高;对于采样率,如果是直接输出 (Direct Output),则采样率越小优先级越高,否则,采样率越大优先级越高。

1.2.3 open流程总结

  • 设备打开流程:
    SwAudioOutputDescriptor 发起请求,最终由 AudioFlinger 处理。
    通过 AudioHwDevice 打开硬件输出流。
    根据需求创建不同类型的音频线程。
  • 线程类型:
    MixerThread:默认混音线程。
    DirectOutputThread:直接输出线程。
    OffloadThread:压缩音频输出线程。
    MmapPlaybackThread:低延迟 MMAP 线程。
  • 主设备设置:
    如果打开的是主输出设备,会将其设置为主硬件设备,并更新硬件状态。
  • 延迟与通知:
    计算并返回输出设备的延迟时间。
    通知客户端输出设备已打开。

参考文章

https://blog.csdn.net/qq_42364999/article/details/146414847?spm=1001.2014.3001.5501

相关推荐
笑鸿的学习笔记15 分钟前
ROS2笔记之服务通信和基于参数的服务通信区别
android·笔记·microsoft
8931519601 小时前
Android开发融云获取多个会话的总未读数
android·android开发·android教程·融云获取多个会话的总未读数·融云未读数
zjw_swun2 小时前
实现了一个uiautomator玩玩
android
pengyu2 小时前
系统化掌握Dart网络编程之Dio(二):责任链模式篇
android·flutter·dart
水w2 小时前
【Android Studio】如何卸载干净(详细步骤)
android·开发语言·android studio·activity
亦是远方2 小时前
2025华为软件精英挑战赛2600w思路分享
android·java·华为
jiet_h2 小时前
深入解析KSP(Kotlin Symbol Processing):现代Android开发的新利器
android·开发语言·kotlin
清晨細雨2 小时前
UniApp集成极光推送详细教程
android·ios·uni-app·极光推送
Li_na_na012 小时前
解决安卓手机WebView无法直接预览PDF的问题(使用PDF.js方案)
android·pdf·uni-app·html5
CYRUS_STUDIO3 小时前
Frida Hook Native:jobjectArray 参数解析
android·c++·逆向