美文网首页
Android音视频三:AudioFlinger和HAL

Android音视频三:AudioFlinger和HAL

作者: 小城哇哇 | 来源:发表于2022-06-14 11:11 被阅读0次

    AudioHAL

    先看看和Audio有关的hal文件 具体路径/hardware/interfaces/audio/文件夹下(这里看的是6.0的)

    大致结构图

    1. IDeviceFactory.hal:打开设备,并返回此设备
    2. IDevice.hal:设备相关的配置,信息,操作等
    3. IStream.hal:输入输出流相关的信息
    4. Callback.hal:返回流相关的状态信息
    5. types.hal:图上没画,因为还不知道是干什么用的

    AudioFlinger和HAL

    在分析AudioFlinger的时候留下的和HAL有关的三个地方

    1. AudioFlinger构造函数:DevicesFactoryHalInterface::create();
    2. loadHwModule_l打开设备:mDevicesFactoryHal->openDevice(name, &dev)
    3. openOutput_l打开流:outHwDev->openOutputStream(...)

    DevicesFactoryHalInterface::create()

    1. 执行流程:DevicesFactoryHalInterface --> FactoryHalHidl --> DevicesFactoryHalHybrid --> DevicesFactoryHalHidl
    2. 结果:返回mDevicesFactoryHal = DevicesFactoryHalHybrid对象,他可以调用IDeviceFactory.hal 里面的方法了

    DevicesFactoryHalInterface.cpp

    # av/media/libaudiohal/DevicesFactoryHalInterface.cpp
    
    // lyh createPreferredImpl方法在FactoryHalHidl.cpp中
    sp<DevicesFactoryHalInterface> DevicesFactoryHalInterface::create() {
        return createPreferredImpl<DevicesFactoryHalInterface>(
                "android.hardware.audio", "IDevicesFactory");
    }
    
    

    FactoryHalHidl.cpp

    # av/media/libaudiohal/FactoryHalHidl.cpp
    
    const char* sAudioHALVersions[] = {"6.0", "5.0", "4.0", "2.0",nullptr};
    
    // lyh 这里传入的两个参数
    // lyh package --> android.hardware.audio
    // lyh interface --> IDevicesFactory
    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;
    }
    
    
    // lyh 真正创建的地方
    bool createHalService(const std::string& version, const std::string& interface,
            void** rawInterface) {
        // lyh 动态库的名称:libaudiohal@x.0.so
        // lyh libaudiohal封装了audio HIDL的接口,以libaudiohal.so的形式供AudioFlinger使用
        const std::string libName = "libaudiohal@" + version + ".so";
        // lyh 猜测是动态库里面的函数名称:createIDevicesFactory
        const std::string factoryFunctionName = "create" + interface;
        constexpr int dlMode = RTLD_LAZY;
        void* handle = nullptr;
        dlerror(); // clear
        // lyh dlopen 加载动态库
        handle = dlopen(libName.c_str(), dlMode);
        if (handle == nullptr) {
            const char* error = dlerror();
            ALOGE("Failed to dlopen %s: %s", libName.c_str(),
                    error != nullptr ? error : "unknown error");
            return false;
        }
        // lyh 用函数指针接受这个create方法
        void* (*factoryFunction)();
        // lyh dlsym 查找方法,返回地址
        *(void **)(&factoryFunction) = dlsym(handle, factoryFunctionName.c_str());
        if (!factoryFunction) {
            const char* error = dlerror();
            ALOGE("Factory function %s not found in library %s: %s",
                    factoryFunctionName.c_str(), libName.c_str(),
                    error != nullptr ? error : "unknown error");
            dlclose(handle);
            return false;
        }
        // lyh 调用
        *rawInterface = (*factoryFunction)();
        ALOGW_IF(!*rawInterface, "Factory function %s from %s returned nullptr",
                factoryFunctionName.c_str(), libName.c_str());
        return true;
    }
    
    // lyh 就是查一下有没有这个本版的HalService
    bool hasHalService(const std::string& package, const std::string& version,
            const std::string& interface) {
        using ::android::hidl::manager::V1_0::IServiceManager;
        // lyh ServiceManager
        sp<IServiceManager> sm = ::android::hardware::defaultServiceManager();
        if (!sm) {
            ALOGE("Failed to obtain HIDL ServiceManager");
            return false;
        }
        // Since audio HAL doesn't support multiple clients, avoid instantiating
        // the interface right away. Instead, query the transport type for it.
        using ::android::hardware::Return;
        using Transport = IServiceManager::Transport;
        // lyh fqName = "android.hardware.audio@x.0::IDevicesFactory"
        const std::string fqName = package + "@" + version + "::" + interface;
        const std::string instance = "default";
        Return<Transport> transport = sm->getTransport(fqName, instance);
        if (!transport.isOk()) {
            ALOGE("Failed to obtain transport type for %s/%s: %s",
                    fqName.c_str(), instance.c_str(), transport.description().c_str());
            return false;
        }
        return transport != Transport::EMPTY;
    }
    
    }  // namespace
    
    
    

    DevicesFactoryHalHybrid.cpp

    # av/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
    
    被调用的方法就在这里
    DevicesFactoryHalHybrid::DevicesFactoryHalHybrid(sp<IDevicesFactory> hidlFactory)
            : mLocalFactory(new DevicesFactoryHalLocal()),
              // 构造函数新建了DevicesFactoryHalHidl对象并赋值,且把service传入
              mHidlFactory(new DevicesFactoryHalHidl(hidlFactory)) {
    }
    
    // lyh FactoryHalHidl加载动态库后调用的方法
    extern "C" __attribute__((visibility("default"))) void* createIDevicesFactory() {
        auto service = hardware::audio::CPP_VERSION::IDevicesFactory::getService();
        // lyh 因为service有值,所以走构造函数,把service传入
        return service ? new CPP_VERSION::DevicesFactoryHalHybrid(service) : nullptr;
    }
    
    

    DevicesFactoryHalHidl.cpp

    # av/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
    
    DevicesFactoryHalHidl::DevicesFactoryHalHidl(sp<IDevicesFactory> devicesFactory) {
        ALOG_ASSERT(devicesFactory != nullptr, "Provided default IDevicesFactory service is NULL");
        // 这个时候就已经把devicesFactory = IDeviceFactory::getService保存起来了,就已经可以和HAL通信了
        addDeviceFactory(devicesFactory, false /*needToNotify*/);
    }
    
    // lyh 熟悉的onFirstRef
    void DevicesFactoryHalHidl::onFirstRef() {
        // lyh 拿到ServiceManager
        sp<IServiceManager> sm = IServiceManager::getService();
        // lyh 创建注册监听
        sp<ServiceNotificationListener> listener = new ServiceNotificationListener(this);
        // lyh 不是很懂这句话真正的意思,
        Return<bool> result = sm->registerForNotifications(
                IDevicesFactory::descriptor, "", listener);
    }
    
    // lyh 不知道基于什么去发送通知,根据方法名像是注册Service时发送的
    class ServiceNotificationListener : public IServiceNotification {
      public:
        explicit ServiceNotificationListener(sp<DevicesFactoryHalHidl> factory)
                : mFactory(factory) {}
        // 
        Return<void> onRegistration(const hidl_string& /*fully_qualified_name*/,
                const hidl_string& instance_name,
                bool /*pre_existing*/) override {
            if (static_cast<std::string>(instance_name) == "default") return Void();
            sp<DevicesFactoryHalHidl> factory = mFactory.promote();
            if (!factory) return Void();
            // lyh HIDL 获取IDeviceFractory.hal
            // lyh /hardware/interfaces/audio/core/
            sp<IDevicesFactory> halFactory = IDevicesFactory::getService(instance_name);
            if (halFactory) {
                factory->addDeviceFactory(halFactory, true /*needToNotify*/);
            }
            return Void();
        }
    
      private:
        wp<DevicesFactoryHalHidl> mFactory;
    };
    DevicesFactoryHalHidl
    
    
    

    loadHwModule_l打开设备

    经过上面的步骤已经可以调用到IDeviceFactory的方法了,所以执行方法也就是走流程的事情

    1. 执行流程:AuioFlinger -> DevicesFactoryHalHidl -> DevicesFactoryHalHybrid -> DeviceFactory -> audio.c(打开设备)
    2. 得到的结果:audio_hw_device_open打开设备,经过包装成IDevice对象返回,然后接着包装返回

    DevicesFactoryHalHybrid.cpp

    # av/media/libaudiohal/impl/DevicesFactoryHalHybrid.cpp
    
    // lyh AudioFlinger调用的方法就是这个
    status_t DevicesFactoryHalHybrid::openDevice(const char *name, sp<DeviceHalInterface> *device) {
        // lyh 根据name值决定使用hidl类还是local类, 区别??
        if (mHidlFactory != 0 && strcmp(AUDIO_HARDWARE_MODULE_ID_A2DP, name) != 0 &&
            strcmp(AUDIO_HARDWARE_MODULE_ID_HEARING_AID, name) != 0) {
            // lyh 这里进入DevicesFactoryHalHidl.cpp
            return mHidlFactory->openDevice(name, device);
        }
        // lyh 这个还不知道是什么时候调用的
        return mLocalFactory->openDevice(name, device);
    }
    
    
    

    DevicesFactoryHalHidl.cpp

    # av/media/libaudiohal/impl/DevicesFactoryHalHidl.cpp
    
    status_t DevicesFactoryHalHidl::openDevice(const char *name, sp<DeviceHalInterface> *device) {
        auto factories = copyDeviceFactories();
    
        // lyh 获取Device类型
        auto hidlId = idFromHal(name, &status);
    
        Result retval = Result::NOT_INITIALIZED;
        for (const auto& factory : factories) {
            // lyh 跨进程调用 --> DevicesFactory,根据类型创建Device
            Return<void> ret = factory->openDevice(
                    hidlId,
                    [&](Result r, const sp<IDevice>& result) {
                        retval = r;
                        if (retval == Result::OK) {
                            // 回调出来的执行 传入IDevice对象,进行一层包装
                            *device = new DeviceHalHidl(result);
                        }
                    });
        }
        return BAD_VALUE;
    }
    
    
    

    DeviceFacotry.cpp

    # hardware/interfaces/audio/core/all-versions/default/DeviceFacotry.cpp
    
    // lyh 这里省略了前面的代码,直接看最后执行的方法,这里的模板类DeviceShim就是Device.cpp
    template <class DeviceShim, class Callback>
    Return<void> DevicesFactory::openDevice(const char* moduleName, Callback _hidl_cb) {
        audio_hw_device_t* halDevice;
        Result retval(Result::INVALID_ARGUMENTS);
        sp<DeviceShim> result;
        // lyh
        int halStatus = loadAudioInterface(moduleName, &halDevice);
        if (halStatus == OK) {
            // lyh DeviceShim 泛形
            result = new DeviceShim(halDevice);
            retval = Result::OK;
        } else if (halStatus == -EINVAL) {
            retval = Result::NOT_INITIALIZED;
        }
        // lyh 回调Callback
        _hidl_cb(retval, result);
        return Void();
    }
    
    
    int DevicesFactory::loadAudioInterface(const char* if_name, audio_hw_device_t** dev) {
        const hw_module_t* mod;
        int rc;
        // lyh hw_get_module_by_class动态链接 hal 库,
        // 如:audio.primary.default.so、audio.a2dp.default.so、audio.usb.default.so
        rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
    
        // lyh open device
        rc = audio_hw_device_open(mod, dev);
    
        return OK;
    }
    
    
    

    openOutput_l打开流

    调用流程:AudioFlinger -> AudioHwDevice -> AudioStreamOut -> DeviceHalHidl -> Device.cpp -> audio.h 得到结果:拿到输出流后,包装成IStreamOut,在向上一层层包装

    AudioFlinger.cpp

    sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l()
    {
        // lyh 找到合适输出设备
        AudioHwDevice *outHwDev = findSuitableHwDev_l(module, deviceType);
        
        // lyh 输出流
        AudioStreamOut *outputStream = NULL;
        // lyh 打开输出流
        status_t status = outHwDev->openOutputStream(
                &outputStream,
                *output,
                deviceType,
                flags,
                config,
                address.string());
    
    
        if (status == NO_ERROR) { 
                ...
        } else {
                // lyh 创建播放线程
                sp<PlaybackThread> thread;
                .... 省略
                return thread;
            }
        }
    
        return 0;
    }
    
    
    

    AudioHwDevice.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;
        // lyh 把自己AudioHwDevice传入
        AudioStreamOut *outputStream = new AudioStreamOut(this, flags);
    
        // lyh 打开流
        status_t status = outputStream->open(handle, deviceType, config, address);
        *ppStreamOut = outputStream;
        return status;
    }
    
    
    

    AudioStreamOut.cpp

    status_t AudioStreamOut::open(
            audio_io_handle_t handle,
            audio_devices_t deviceType,
            struct audio_config *config,
            const char *address)
    {
        sp<StreamOutHalInterface> outStream;
    
        // lyh 调用DeviceHalHidl的方法,hwDev就是获取DeviceHalHidl对象
        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);
        }
    
        return status;
    }
    
    
    

    DeviceHalHidl.cpp

    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) {
        if (mDevice == 0) return NO_INIT;
        DeviceAddress hidlDevice;
        status_t status = deviceAddressFromHal(deviceType, address, &hidlDevice);
        if (status != OK) return status;
        AudioConfig hidlConfig;
        HidlUtils::audioConfigFromHal(*config, &hidlConfig);
        Result retval = Result::NOT_INITIALIZED;
        // lyh IDevice
        Return<void> ret = mDevice->openOutputStream(.hal
                handle,
                hidlDevice,
                hidlConfig,
                EnumBitfield<AudioOutputFlag>(flags),
    #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);
    }
    
    
    

    相关文章

      网友评论

          本文标题:Android音视频三:AudioFlinger和HAL

          本文链接:https://www.haomeiwen.com/subject/syczmrtx.html