19

Android 12(S) 图像显示系统 - HWC HAL 初始化与调用流程 - 二的次方

 1 year ago
source link: https://www.cnblogs.com/roger-yu/p/16354419.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

必读:

Android 12(S) 图像显示系统 - 开篇


源码位置:/hardware/interfaces/graphics/composer/

在源码目录下可以看到4个版本的HIDL Interface定义,最新版本是2.4,也是目前我的测试平台在用的,不同版本使用带有版本号的包名来区分,例如 :package [email protected]
各版本中均有相同的接口,并且具有继承关系,新版本继承旧版接口并扩展了新方法。

/frameworks/native/services/surfaceflinger/DisplayHardware/ 中 android::Hwc2::impl::Composer 相当于HIDL的客户端,framework通过impl::Composer中的方法看跨进程和 hwc hal 互动。

各个版本接口的继承关系

979092-20220628144301025-633697616.jpg

Composer HIDL Service

代码位置
/hardware/interfaces/graphics/composer/2.4/default/service.cpp
/hardware/interfaces/graphics/composer/2.4/default/[email protected]

开机启动时,init进程解析rc文件带起服务进程,在service.cpp的main函数中,注册服务

int main() {
    ...
    android::sp<IComposer> composer = HwcLoader::load();
    if (composer == nullptr) {
        return 1;
    }
    if (composer->registerAsService() != android::NO_ERROR) {
        ALOGE("failed to register service");
        return 1;
    }
    ...
}

可以看到其中调用了一个非常重要的方法HwcLoader::load(),看其代码:

[/hardware/interfaces/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcLoader.h]
static IComposer* load() {
    const hw_module_t* module = loadModule();
    if (!module) {
        return nullptr;
    }
    auto hal = createHalWithAdapter(module);
    if (!hal) {
        return nullptr;
    }
    return createComposer(std::move(hal)).release();
}

再看loadModule的定义,去找HAL library中定义的HAL_MODULE_INFO_SYM结构体变量

[/hardware/interfaces/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h]
static const hw_module_t* loadModule() {
    const hw_module_t* module;
    int error = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
    if (error) {
        ALOGI("falling back to gralloc module");
        error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
    }
    if (error) {
        ALOGE("failed to get hwcomposer or gralloc module");
        return nullptr;
    }
    return module;
}

可以看到基本的调用流程:
开机启动 ==> HwcLoader::load() ==> HwcLoader::loadModule() ==> hw_get_module

hw_get_module就是去打开Vendor厂商实现的HWC HAL模块,这个流程本质上还是旧有的HAL打开方式,只是外包装了一层HIDL。
最终得到一个指向HWC module的hw_module_t指针

再回到HwcLoader::load()方法中,接下来就是  createHalWithAdapter ==>  createComposer

先看 createHalWithAdapter 做了哪些工作

[/hardware/interfaces/graphics/composer/2.4/utils/passthrough/include/composer-passthrough/2.4/HwcLoader.h]
// create a ComposerHal instance, insert an adapter if necessary
static std::unique_ptr<hal::ComposerHal> createHalWithAdapter(const hw_module_t* module) {
    bool adapted;
    hwc2_device_t* device = openDeviceWithAdapter(module, &adapted);
    if (!device) {
        return nullptr;
    }
    auto hal = std::make_unique<HwcHal>();
    return hal->initWithDevice(std::move(device), !adapted) ? std::move(hal) : nullptr;
}

其中调用了openDeviceWithAdapter去打开 hwc2_device_t

[/hardware/interfaces/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcLoader.h]
// open hwcomposer2 device, install an adapter if necessary
static hwc2_device_t* openDeviceWithAdapter(const hw_module_t* module, bool* outAdapted) {
    if (module->id && std::string(module->id) == GRALLOC_HARDWARE_MODULE_ID) {
        *outAdapted = true;
        return adaptGrallocModule(module);
    }
    hw_device_t* device;
    int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
    if (error) {
        ALOGE("failed to open hwcomposer device: %s", strerror(-error));
        return nullptr;
    }
    int major = (device->version >> 24) & 0xf;
    if (major != 2) {
        *outAdapted = true;
        return adaptHwc1Device(std::move(reinterpret_cast<hwc_composer_device_1*>(device)));
    }
    *outAdapted = false;
        return reinterpret_cast<hwc2_device_t*>(device);
}

openDeviceWithAdapter中调用了open方法

hw_device_t* device;
int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);

这样就获取到了 hwc2_device

typedef struct hwc2_device {
     struct hw_device_t common;
     void (*getCapabilities)(struct hwc2_device* device, uint32_t* outCount,
            int32_t* /*hwc2_capability_t*/outCapabilities);
     hwc2_function_pointer_t (*getFunction)(struct hwc2_device* device,
            int32_t /*hwc2_function_descriptor_t*/descriptor);
} hwc2_device_t;

回到createHalWithAdapter中再调用initWithDevice及保存到了HwcHal中的mDevice这个变量中

bool initWithDevice(hwc2_device_t* device, bool requireReliablePresentFence) {
    // we own the device from this point on
    mDevice = device;
    ….
}

getFunction函数关联到了 vendor 厂商实现的hwc hal中具体实现,这个函数通过函数描述符来获取对应的函数指针。

initDispatch的作用介绍

initDispatch()来初始化HWC通用的函数指针

 

979092-20220628143758914-2012492437.png

2.4 <---2.3<---2.2<---2.1 版本的initDispatch()会被调用到来初始化函数指针

在这里就是把mDispatch函数指针和HWC HAL具体实现的方法一一对应起来

注意一下继承关系:
V2_1
class HwcHalImpl : public Hal

V2_2 
class HwcHalImpl : public V2_1::passthrough::detail::HwcHalImpl<Hal>

V2_3
class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal>

V2_4
class HwcHalImpl : public V2_3::passthrough::detail::HwcHalImpl<Hal>

各个版本的HwcHalImpl类中都有定义一个结构体变量mDispatch,这个结构体的成员变量均为函数指针,是以 HWC2_PFN_* 开头的函数指针类型。

struct {
    HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges;
    HWC2_PFN_CREATE_LAYER createLayer;
    ……
    HWC2_PFN_VALIDATE_DISPLAY validateDisplay;
} mDispatch = {};

initDispatch通过调用vendor厂商实现的hwc hal中的getFunction方法获取到descriptor对应的函数指针,并保存到mDispatch的成员中

template <typename T>
bool initDispatch(hwc2_function_descriptor_t desc, T* outPfn) {
   auto pfn = mDevice->getFunction(mDevice, desc);
   if (pfn) {
       *outPfn = reinterpret_cast<T>(pfn);
       return true;
   } else {
       ALOGE("failed to get hwcomposer2 function %d", desc);
       return false;
   }
}

简单总结下上述的分析内容

    1. 开机后启动了一个名字为[email protected]的服务进程,用于 framework 和 hwc hal 的通信;
    2. 这个composer service启动时,进行了必要的初始化工作,主要就是loadModule和openDevice,在这一过程中获取到hal层实现的函数的指针,
    并保存在了mDispatch中
    3. 之后运行时,framework 呼叫功能时,本质就是通过mDispatch持有的函数指针调用到 hwc hal 的具体实现

Framework 与 hwc hal通信的流程

直接打印调用栈信息来展示这一流程,以其中的setClientTarget这个方法的调用过程为例:

SurfaceFlinger进程的调用栈信息

11-13 00:47:20.455   224   224 E HwcComposer: stackdump:#00 pc 00086f8f  /system/bin/surfaceflinger (android::Hwc2::impl::Composer::setClientTarget(unsigned long long, unsigned int, android::sp<android::GraphicBuffer> const&, int, android::hardware::graphics::common::V1_2::Dataspace, std::__1::vector<android::hardware::graphics::composer::V2_1::IComposerClient::Rect, std::__1::allocator<android::hardware::graphics::composer::V2_1::IComposerClient::Rect> > const&)+182)
11-13 00:47:20.455   224   224 E HwcComposer: stackdump:#01 pc 00096791  /system/bin/surfaceflinger (android::impl::HWComposer::setClientTarget(android::HalDisplayId, unsigned int, android::sp<android::Fence> const&, android::sp<android::GraphicBuffer> const&, android::hardware::graphics::common::V1_2::Dataspace)+408)
11-13 00:47:20.455   224   224 E HwcComposer: stackdump:#02 pc 0008e881  /system/bin/surfaceflinger (android::FramebufferSurface::advanceFrame()+332)
11-13 00:47:20.455   224   224 E HwcComposer: stackdump:#03 pc 00122a55  /system/bin/surfaceflinger (android::compositionengine::impl::RenderSurface::queueBuffer(android::base::unique_fd_impl<android::base::DefaultCloser>)+436)
11-13 00:47:20.455   224   224 E HwcComposer: stackdump:#04 pc 001069ed  /system/bin/surfaceflinger (android::compositionengine::impl::Output::finishFrame(android::compositionengine::CompositionRefreshArgs const&)+168)
11-13 00:47:20.455   224   224 E HwcComposer: stackdump:#05 pc 00100c89  /system/bin/surfaceflinger (android::compositionengine::impl::Display::finishFrame(android::compositionengine::CompositionRefreshArgs const&)+76)
11-13 00:47:20.455   224   224 E HwcComposer: stackdump:#06 pc 001054ef  /system/bin/surfaceflinger (android::compositionengine::impl::Output::present(android::compositionengine::CompositionRefreshArgs const&)+114)
11-13 00:47:20.455   224   224 E HwcComposer: stackdump:#07 pc 000ff727  /system/bin/surfaceflinger (android::compositionengine::impl::CompositionEngine::present(android::compositionengine::CompositionRefreshArgs&)+146)
11-13 00:47:20.455   224   224 E HwcComposer: stackdump:#08 pc 000d600b  /system/bin/surfaceflinger (android::SurfaceFlinger::onMessageRefresh()+1530)
11-13 00:47:20.455   224   224 E HwcComposer: stackdump:#09 pc 000d570d  /system/bin/surfaceflinger (android::SurfaceFlinger::onMessageInvalidate(long long, long long)+8784)
11-13 00:47:20.455   224   224 E HwcComposer: stackdump:#10 pc 000b9907  /system/bin/surfaceflinger (android::impl::MessageQueue::Handler::handleMessage(android::Message const&)+94)
11-13 00:47:20.456   224   224 E HwcComposer: stackdump:#11 pc 00010179  /system/lib/libutils.so (android::Looper::pollInner(int)+288)
11-13 00:47:20.456   224   224 E HwcComposer: stackdump:#12 pc 0000ffff  /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+62)
11-13 00:47:20.456   224   224 E HwcComposer: stackdump:#13 pc 000b9dd1  /system/bin/surfaceflinger (android::impl::MessageQueue::waitMessage()+56)
11-13 00:47:20.456   224   224 E HwcComposer: stackdump:#14 pc 000cc50d  /system/bin/surfaceflinger (android::SurfaceFlinger::run()+6)
11-13 00:47:20.456   224   224 E HwcComposer: stackdump:#15 pc 000ff253  /system/bin/surfaceflinger (main+1182)
11-13 00:47:20.456   224   224 E HwcComposer: stackdump:#16 pc 0003253b  /apex/com.android.runtime/lib/bionic/libc.so (__libc_init+54)

HWC HAL端的调用栈信息 

11-08 06:04:30.920   339   339 E hwc_display: stackdump:#00 pc 000287cb  /vendor/lib/hw/hwcomposer.stark.so (Display::setClientTarget(native_handle const*, int, int, hwc_region)+90)
11-08 06:04:30.920   339   339 E hwc_display: stackdump:#01 pc 00023255  /vendor/lib/hw/hwcomposer.stark.so (hwc_setClientTarget(hwc2_device*, unsigned long long, native_handle const*, int, int, hwc_region)+56)
11-08 06:04:30.920   339   339 E hwc_display: stackdump:#02 pc 00007d93  /vendor/bin/hw/[email protected] (android::hardware::graphics::composer::V2_1::passthrough::detail::HwcHalImpl<android::hardware::graphics::composer::V2_4::hal::ComposerHal>::setClientTarget(unsigned long long, native_handle const*, int, int, std::__1::vector<hwc_rect, std::__1::allocator<hwc_rect> > const&)+40)
11-08 06:04:30.920   339   339 E hwc_display: stackdump:#03 pc 00010b11  /vendor/bin/hw/[email protected] (android::hardware::graphics::composer::V2_1::hal::ComposerCommandEngine::executeSetClientTarget(unsigned short)+244)
11-08 06:04:30.920   339   339 E hwc_display: stackdump:#04 pc 0000ed3f  /vendor/bin/hw/[email protected] (android::hardware::graphics::composer::V2_1::hal::ComposerCommandEngine::execute(unsigned int, android::hardware::hidl_vec<android::hardware::hidl_handle> const&, bool*, unsigned int*, android::hardware::hidl_vec<android::hardware::hidl_handle>*)+86)
11-08 06:04:30.920   339   339 E hwc_display: stackdump:#05 pc 0000d0a1  /vendor/bin/hw/[email protected] (android::hardware::graphics::composer::V2_1::hal::detail::ComposerClientImpl<android::hardware::graphics::composer::V2_3::IComposerClient, android::hardware::graphics::composer::V2_3::hal::ComposerHal>::executeCommands(unsigned int, android::hardware::hidl_vec<android::hardware::hidl_handle> const&, std::__1::function<void (android::hardware::graphics::composer::V2_1::Error, bool, unsigned int, android::hardware::hidl_vec<android::hardware::hidl_handle> const&)>)+84)
11-08 06:04:30.920   339   339 E hwc_display: stackdump:#06 pc 0001df97  /vendor/lib/[email protected] (android::hardware::graphics::composer::V2_2::BnHwComposerClient::_hidl_executeCommands_2_2(android::hidl::base::V1_0::BnHwBase*, android::hardware::Parcel const&, android::hardware::Parcel*, std::__1::function<void (android::hardware::Parcel&)>)+294)
11-08 06:04:30.920   339   339 E hwc_display: stackdump:#07 pc 0003182f  /vendor/lib/[email protected] (android::hardware::graphics::composer::V2_4::BnHwComposerClient::onTransact(unsigned int, android::hardware::Parcel const&, android::hardware::Parcel*, unsigned int, std::__1::function<void (android::hardware::Parcel&)>)+1198)
11-08 06:04:30.920   339   339 E hwc_display: stackdump:#08 pc 000546d9  /apex/com.android.vndk.v31/lib/libhidlbase.so (android::hardware::BHwBinder::transact(unsigned int, android::hardware::Parcel const&, android::hardware::Parcel*, unsigned int, std::__1::function<void (android::hardware::Parcel&)>)+96)
11-08 06:04:30.920   339   339 E hwc_display: stackdump:#09 pc 000536a7  /apex/com.android.vndk.v31/lib/libhidlbase.so (android::hardware::IPCThreadState::getAndExecuteCommand()+974)
11-08 06:04:30.920   339   339 E hwc_display: stackdump:#10 pc 00053239  /apex/com.android.vndk.v31/lib/libhidlbase.so (android::hardware::IPCThreadState::joinThreadPool(bool)+56)
11-08 06:04:30.920   339   339 E hwc_display: stackdump:#11 pc 000070fb  /vendor/bin/hw/[email protected] (main+270)
11-08 06:04:30.920   339   339 E hwc_display: stackdump:#12 pc 0003253b  /apex/com.android.runtime/lib/bionic/libc.so (__libc_init+54)

发起端:

[/frameworks/native/services/surfaceflinger/DisplayHardware/ComposerHal.cpp]
Error Composer::setClientTarget(Display display, uint32_t slot,
        const sp<GraphicBuffer>& target,
        int acquireFence, Dataspace dataspace,
        const std::vector<IComposerClient::Rect>& damage)
{
    mWriter.selectDisplay(display);
    const native_handle_t* handle = nullptr;
    if (target.get()) {
        handle = target->getNativeBuffer()->handle;
    }
    mWriter.setClientTarget(slot, handle, acquireFence, dataspace, damage);
    return Error::NONE;
}

中转站:

[/hardware/interfaces/graphics/composer/2.1/utils/command-buffer/include/composer-command-buffer/2.1/ComposerCommandBuffer.h]
void setClientTargetInternal(...) {
    beginCommand(IComposerClient::Command::SET_CLIENT_TARGET, length);
    ...
    endCommand();
}
 跨进程了
[/hardware/interfaces/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h]
virtual bool executeCommand(IComposerClient::Command command, uint16_t length) {
    switch (command) {
    ...
        case IComposerClient::Command::SET_CLIENT_TARGET:
            return executeSetClientTarget(length);
    }
}


bool executeSetClientTarget(uint16_t length) {
    ...
    err = mHal->setClientTarget(mCurrentDisplay, clientTarget, fence, dataspace, damage);
    ...
}

处理终端:

Vendor厂商实现的HAL,具体实现setClientTarget的功能 



About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK