Android音视频三:AudioFlinger和HAL

AudioHAL

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

大致结构图

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

image.png

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 里面的方法了

image.png

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 动态库的名称:[email protected]
	// 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 = "[email protected]::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对象返回,然后接着包装返回

image.png

image.png

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);
}

复制代码

猜你喜欢

转载自juejin.im/post/7104570997038120968