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

相关推荐
似霰1 小时前
安卓adb shell串口基础指令
android·adb
fatiaozhang95273 小时前
中兴云电脑W102D_晶晨S905X2_2+16G_mt7661无线_安卓9.0_线刷固件包
android·adb·电视盒子·魔百盒刷机·魔百盒固件
CYRUS_STUDIO4 小时前
Android APP 热修复原理
android·app·hotfix
鸿蒙布道师5 小时前
鸿蒙NEXT开发通知工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
鸿蒙布道师5 小时前
鸿蒙NEXT开发网络相关工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
大耳猫5 小时前
【解决】Android Gradle Sync 报错 Could not read workspace metadata
android·gradle·android studio
ta叫我小白5 小时前
实现 Android 图片信息获取和 EXIF 坐标解析
android·exif·经纬度
dpxiaolong7 小时前
RK3588平台用v4l工具调试USB摄像头实践(亮度,饱和度,对比度,色相等)
android·windows
tangweiguo030519878 小时前
Android 混合开发实战:统一 View 与 Compose 的浅色/深色主题方案
android
老狼孩111228 小时前
2025新版懒人精灵零基础及各板块核心系统视频教程-全分辨率免ROOT自动化开发
android·机器人·自动化·lua·脚本开发·懒人精灵·免root开发