hwc2 surfaceflinger启动流程分析

先还是大体的来看下流程图,这个比hwc1复杂了好多,不是太好理解:
在这里插入图片描述

1.SurfaceFlinger.init

        "Starting with vr flinger active is not currently supported.");mRealHwc = new HWComposer(false);mHwc = mRealHwc;mHwc->setEventHandler(static_cast<HWComposer::EventHandler*>(this));Mutex::Autolock _l(mStateLock);

在这里只关注hwcomposer实例生成的具体过程,上面代码主要二个作用:
1.生成一个HWComposer实例
2.生成实例后,注意消息回调函数。是surfaceflinger与composer Hidl服务层通信的唯一通道

2.HWComposer

HWComposer::HWComposer(bool useVrComposer): mHwcDevice(),mDisplayData(2),mFreeDisplaySlots(),mHwcDisplaySlots(),mCBContext(),mEventHandler(nullptr),mVSyncCounts(),mRemainingHwcVirtualDisplays(0)
{for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {mLastHwVSync[i] = 0;mVSyncCounts[i] = 0;}loadHwcModule(useVrComposer);
}

来看看其构造函数,除了初始化一些基本的成员变量。剩下的就是loadHwcModule这个API的调用了,这个调用就是获取hwc2的实例

3.loadHwcModule

文件:HWComposer.cpp

void HWComposer::loadHwcModule(bool useVrComposer)
{ALOGV("loadHwcModule");//获取HWC2::Device类实例,这是这个函数的唯一作用mHwcDevice = std::make_unique<HWC2::Device>(useVrComposer);mRemainingHwcVirtualDisplays = mHwcDevice->getMaxVirtualDisplayCount();
}

4.HWC2::Device

文件:hwc2.cpp

Device::Device(bool useVrComposer): mComposer(std::make_unique<Hwc2::Composer>(useVrComposer)),mCapabilities(),mDisplays(),mHotplug(),mPendingHotplugs(),mRefresh(),mPendingRefreshes(),mVsync(),mPendingVsyncs()
{loadCapabilities();registerCallbacks();
}

这个函数比较重要的有二个:
1.mComposer成员的初始化
2.向composer HIDL服务注册回调函数registerCallbacks

5.Composer

文件:ComposerHal.cpp

Composer::Composer(bool useVrComposer): mWriter(kWriterInitialSize),mIsUsingVrComposer(useVrComposer)
{if (mIsUsingVrComposer) {mComposer = IComposer::getService("vr");} else {mComposer = IComposer::getService(); // use default name}if (mComposer == nullptr) {LOG_ALWAYS_FATAL("failed to get hwcomposer service");}mComposer->createClient([&](const auto& tmpError, const auto& tmpClient){if (tmpError == Error::NONE) {mClient = tmpClient;}});if (mClient == nullptr) {LOG_ALWAYS_FATAL("failed to create composer client");}if (mIsUsingVrComposer) {sp<IVrComposerClient> vrClient = IVrComposerClient::castFrom(mClient);if (vrClient == nullptr) {LOG_ALWAYS_FATAL("failed to create vr composer client");}}
}

以上是Composer的构造函数,主要作用:
1.获取 android.hardware.graphics.composer@2.1-service这个服务的实例
2.创建一个用户消息通信的client

6.registerCallback

文件:ComposerHal.cpp

void Composer::registerCallback(const sp<IComposerCallback>& callback)
{auto ret = mClient->registerCallback(callback);if (!ret.isOk()) {ALOGE("failed to register IComposerCallback");}
}

hwc2.cpp里面的registerCallback会调用 这里的registerCallback函数,而此函数又是通过获取服务生成的client对象,就callback消息回调接口注册到服务层
到这里,surfaceflinger端的初始后结束。然后继续来看下composer@2.1-service这个服务的加载过程

7.composer@2.1-service

文件路径:hardware\interfaces\graphics\composer\2.1\default
文件名:service.cpp


int main() {// the conventional HAL might start binder servicesandroid::ProcessState::initWithDriver("/dev/vndbinder");android::ProcessState::self()->setThreadPoolMaxThreadCount(4);android::ProcessState::self()->startThreadPool();// same as SF main threadstruct sched_param param = {0};param.sched_priority = 2;if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK,&param) != 0) {ALOGE("Couldn't set SCHED_FIFO: %d", errno);}return defaultPassthroughServiceImplementation<IComposer>(4);
}

这是个main函数的主要内容,就是加载IComposer服务。然后我们来看看 android.bp文件看其描述编译生成的内容:


cc_binary {name: "***android.hardware.graphics.composer@2.1-service***",defaults: ["hidl_defaults"],proprietary: true,relative_install_path: "hw",srcs: ["service.cpp"],init_rc: ["android.hardware.graphics.composer@2.1-service.rc"],static_libs: ["libhwcomposer-client"],shared_libs: ["android.hardware.graphics.composer@2.1","libbase","libbinder","libcutils","libfmq","libhardware","libhidlbase","libhidltransport","liblog","libsync","libutils",],

8.IComposer

文件路径:hardware\interfaces\graphics\composer\2.1\default
文件名:hwc.cpp

IComposer* HIDL_FETCH_IComposer(const char*)
{const hw_module_t* module = nullptr;int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);if (err) {ALOGE("failed to get hwcomposer module");return nullptr;}return new HwcHal(module);
}

这里来到了熟悉的硬件HAL的加载处理了,主要就用dlopen我们指定的so,这个SO就是硬件适配层
然后我们来看看其构造函数的实现:

HwcHal::HwcHal(const hw_module_t* module): mDevice(nullptr), mDispatch(), mAdapter()
{// Determine what kind of module is available (HWC2 vs HWC1.X).hw_device_t* device = nullptr;int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);if (error != 0) {ALOGE("Failed to open HWC device (%s), aborting", strerror(-error));abort();}uint32_t majorVersion = (device->version >> 24) & 0xF;// If we don't have a HWC2, we need to wrap whatever we have in an adapter.if (majorVersion != 2) {uint32_t minorVersion = device->version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;minorVersion = (minorVersion >> 16) & 0xF;ALOGI("Found HWC implementation v%d.%d", majorVersion, minorVersion);if (minorVersion < 1) {ALOGE("Cannot adapt to HWC version %d.%d. Minimum supported is 1.1",majorVersion, minorVersion);abort();}mAdapter = std::make_unique<HWC2On1Adapter>(reinterpret_cast<hwc_composer_device_1*>(device));// Place the adapter in front of the device module.mDevice = mAdapter.get();} else {mDevice = reinterpret_cast<hwc2_device_t*>(device);}initCapabilities();if (majorVersion >= 2 &&hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) {ALOGE("Present fence must be reliable from HWC2 on.");abort();}initDispatch();
}

其主要作用就是,根据我们加载的so,使用其open接口获取device结构体,此结构体指定了各种回调API
initDispatch这个调用就是从SO中获取对应的函数地址

9.createClient

Return<void> HwcHal::createClient(createClient_cb hidl_cb)
{Error err = Error::NONE;sp<ComposerClient> client;{std::lock_guard<std::mutex> lock(mClientMutex);// only one client is allowedif (mClient == nullptr) {client = new ComposerClient(*this);client->initialize();mClient = client;} else {err = Error::NO_RESOURCES;}}hidl_cb(err, client);return Void();
}

上面说过surfaceflinger主要是通过这个client进行消息通信,那么上面就是createClient的具体实现,surfaceflinger就是调用这个函数获取ComposerClient这个类的实例

void HwcHal::enableCallback(bool enable)
{if (enable) {mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,reinterpret_cast<hwc2_function_pointer_t>(refreshHook));mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,reinterpret_cast<hwc2_function_pointer_t>(vsyncHook));} else {mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,nullptr);mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,nullptr);mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,nullptr);}
}

上面段代码是registerCallback最终的处理地方,向hal注册消息回调接口

10.HAL

上面的composer服务就是一个中转的过程。负责承接应和和HAL,下面我们就来看看HAL的加载过程
文件路径:\hardware\qcom\display\msm8998\sdm\libs

11.HWCSession::Open

文件名:hwc_session.cpp

hwc_module_t HAL_MODULE_INFO_SYM = {.common = {.tag = HARDWARE_MODULE_TAG,.version_major = 3,.version_minor = 0,.id = HWC_HARDWARE_MODULE_ID,.name = "QTI Hardware Composer Module",.author = "CodeAurora Forum",.methods = &g_hwc_module_methods,.dso = 0,.reserved = {0},}
};class HWCSession : hwc2_device_t, public qClient::BnQClient {public:struct HWCModuleMethods : public hw_module_methods_t {HWCModuleMethods() { hw_module_methods_t::open = HWCSession::Open; }};

我们service层就是调用open获取设备的结构体指针,上面代码很明显open实际上是调用的HWCSession::Open函数,我们来看看这个open的实现

12.HWCSession::Open

int HWCSession::Open(const hw_module_t *module, const char *name, hw_device_t **device) {SCOPE_LOCK(locker_);if (!module || !name || !device) {DLOGE("Invalid parameters.");return -EINVAL;}if (!strcmp(name, HWC_HARDWARE_COMPOSER)) {HWCSession *hwc_session = new HWCSession(module);if (!hwc_session) {return -ENOMEM;}int status = hwc_session->Init();if (status != 0) {return status;}hwc2_device_t *composer_device = hwc_session;*device = reinterpret_cast<hw_device_t *>(composer_device);}return 0;
}

上面的代码很清楚,主要两个作用:
1.生成一个HWCSession实例
2.调用这个实例的init接口来初始化

13.init

int HWCSession::Init() {int status = -EINVAL;const char *qservice_name = "display.qservice";//获取display.qservice这个服务// Start QService and connect to it.qService::QService::init();android::sp<qService::IQService> iqservice = android::interface_cast<qService::IQService>(android::defaultServiceManager()->getService(android::String16(qservice_name)));if (iqservice.get()) {iqservice->connect(android::sp<qClient::IQClient>(this));qservice_ = reinterpret_cast<qService::QService *>(iqservice.get());} else {DLOGE("Failed to acquire %s", qservice_name);return -EINVAL;}//生成HWCBufferAllocator实例,这个主要是打开GRALLOC_HARDWARE_MODULE_ID这个设备也就是framebufferbuffer_allocator_ = new HWCBufferAllocator();DisplayError error = CoreInterface::CreateCore(HWCDebugHandler::Get(), buffer_allocator_,&buffer_sync_handler_, &socket_handler_,&core_intf_);if (error != kErrorNone) {DLOGE("Display core initialization failed. Error = %d", error);return -EINVAL;}// Read which display is first, and create it and store it in primary slot// TODO(user): This will need to be redone for HWC2 - right now we validate only// the primary physical pathHWDisplayInterfaceInfo hw_disp_info;error = core_intf_->GetFirstDisplayInterfaceType(&hw_disp_info);if (error == kErrorNone && hw_disp_info.type == kHDMI && hw_disp_info.is_connected) {// HDMI is primary display. If already connected, then create it and store in// primary display slot. If not connected, create a NULL display for now.status = HWCDisplayExternal::Create(core_intf_, buffer_allocator_, &callbacks_, qservice_,&hwc_display_[HWC_DISPLAY_PRIMARY]);} else {// Create and power on primary displaystatus = HWCDisplayPrimary::Create(core_intf_, buffer_allocator_, &callbacks_, qservice_,&hwc_display_[HWC_DISPLAY_PRIMARY]);}if (status) {CoreInterface::DestroyCore();return status;}color_mgr_ = HWCColorManager::CreateColorManager(buffer_allocator_);if (!color_mgr_) {DLOGW("Failed to load HWCColorManager.");}//创建线程获取驱动发出来的uevent消息if (pthread_create(&uevent_thread_, NULL, &HWCUeventThread, this) < 0) {DLOGE("Failed to start = %s, error = %s", uevent_thread_name_, strerror(errno));HWCDisplayPrimary::Destroy(hwc_display_[HWC_DISPLAY_PRIMARY]);hwc_display_[HWC_DISPLAY_PRIMARY] = 0;CoreInterface::DestroyCore();return -errno;}struct rlimit fd_limit = {};getrlimit(RLIMIT_NOFILE, &fd_limit);fd_limit.rlim_cur = fd_limit.rlim_cur * 2;if (fd_limit.rlim_cur < fd_limit.rlim_max) {auto err = setrlimit(RLIMIT_NOFILE, &fd_limit);if (err) {DLOGW("Unable to increase fd limit -  err:%d, %s", errno, strerror(errno));}}return 0;
}

上面的初始化主要作用有:
1.获取display.qservice服务实例
2.获取GRALLOC_HARDWARE_MODULE_ID设备
3.创建primary display设备,此设备最终后通过线程读取msm_drm节点信息,然后上报vsync消息,这里就不继续介绍了
4.开启线程等待接收内核socket消息,然后通过callback传给上层

hwc2分了三层:
一,第一层就是surfaceflinger其本身
二,第二层就是composer@2.1这个服务进程,作为中间环节打通上层层,第一层通过getservice获取实例进行通过
三,第三层就是HAL层,第二层通过dlopen的方式获取句柄。这层主要是与驱动进行通信。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平