AIDL Hal 开发指南5 —— stable-c HAL 实例分析

704 阅读2分钟

在 HIDL HAL 中我们聊过 Same-Process HALs,这类 hal 的调用对性能要求高,一般直接链接,不适用跨进程的方式来调用。

在 AIDL HAL 中,与之对应的是 stable-c HAL。stable-c HAL 就是一个对外接口稳定的 so 库。

接着我们来看一个源码中的 stable-c HAL, hardware/interfaces/graphics/mapper

image.png 这里只是给出一个框架,具体需要芯片厂商来做实现。

其中最重要的就是 hardware/interfaces/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperProvider.h,其中的 IMapperV5Impl就是 stable-c HAL 的对外接口:

struct IMapperV5Impl {
    static const auto version = AIMAPPER_VERSION_5;
    virtual ~IMapperV5Impl() = default;

    virtual AIMapper_Error importBuffer(const native_handle_t* _Nonnull handle,
                                        buffer_handle_t _Nullable* _Nonnull outBufferHandle) = 0;

    virtual AIMapper_Error freeBuffer(buffer_handle_t _Nonnull buffer) = 0;

    virtual AIMapper_Error getTransportSize(buffer_handle_t _Nonnull buffer,
                                            uint32_t* _Nonnull outNumFds,
                                            uint32_t* _Nonnull outNumInts) = 0;

    virtual AIMapper_Error lock(buffer_handle_t _Nonnull buffer, uint64_t cpuUsage,
                                ARect accessRegion, int acquireFence,
                                void* _Nullable* _Nonnull outData) = 0;

    virtual AIMapper_Error unlock(buffer_handle_t _Nonnull buffer, int* _Nonnull releaseFence) = 0;

    virtual AIMapper_Error flushLockedBuffer(buffer_handle_t _Nonnull buffer) = 0;

    virtual AIMapper_Error rereadLockedBuffer(buffer_handle_t _Nonnull buffer) = 0;

    virtual int32_t getMetadata(buffer_handle_t _Nonnull buffer, AIMapper_MetadataType metadataType,
                                void* _Nullable destBuffer, size_t destBufferSize) = 0;

    virtual int32_t getStandardMetadata(buffer_handle_t _Nonnull buffer,
                                        int64_t standardMetadataType, void* _Nullable destBuffer,
                                        size_t destBufferSize) = 0;

    virtual AIMapper_Error setMetadata(buffer_handle_t _Nonnull buffer,
                                       AIMapper_MetadataType metadataType,
                                       const void* _Nonnull metadata, size_t metadataSize) = 0;

    virtual AIMapper_Error setStandardMetadata(buffer_handle_t _Nonnull buffer,
                                               int64_t standardMetadataType,
                                               const void* _Nonnull metadata,
                                               size_t metadataSize) = 0;

    virtual AIMapper_Error listSupportedMetadataTypes(
            const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList,
            size_t* _Nonnull outNumberOfDescriptions) = 0;

    virtual AIMapper_Error dumpBuffer(buffer_handle_t _Nonnull bufferHandle,
                                      AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
                                      void* _Null_unspecified context) = 0;

    virtual AIMapper_Error dumpAllBuffers(
            AIMapper_BeginDumpBufferCallback _Nonnull beginDumpBufferCallback,
            AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
            void* _Null_unspecified context) = 0;

    virtual AIMapper_Error getReservedRegion(buffer_handle_t _Nonnull buffer,
                                             void* _Nullable* _Nonnull outReservedRegion,
                                             uint64_t* _Nonnull outReservedSize) = 0;
};

Google 给出了一个模拟器的实现 /external/minigbm/cros_gralloc/mapper_stablec

external/minigbm/cros_gralloc/mapper_stablec/Mapper.cpp 中实现了一个 CrosGrallocMapperV5 类继承自 IMapperV5Impl,实现了所有的对外接口。

另外,定义了两个对外的入口符号:

extern "C" uint32_t ANDROID_HAL_MAPPER_VERSION = AIMAPPER_VERSION_5;

extern "C" AIMapper_Error AIMapper_loadIMapper(AIMapper* _Nullable* _Nonnull outImplementation) {
    static vendor::mapper::IMapperProvider<CrosGrallocMapperV5> provider;
    return provider.load(outImplementation);
}

使用 mapper hal 的程序可以通过 AIMapper_loadIMapper 获取 AIMapper 指针,AIMapper 内部的函数最终都会调用到 CrosGrallocMapperV5 类中的具体实现中。

这里两个符号都使用 extern "C" 修饰,也就是, c 和 cpp 程序都可以使用这两个符号来使用 mmaper 模块。