先还是大体的来看下流程图,这个比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的方式获取句柄。这层主要是与驱动进行通信。

hwc2 surfaceflinger启动流程分析相关推荐

  1. 解析并符号 读取dll_Spring IOC容器之XmlBeanFactory启动流程分析和源码解析

    一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...

  2. Zygote进程启动流程分析

    文中的源代码版本为api23 Zygote进程启动流程分析 先说结论,zygote进程启动过程中主要做了下面这些事情: 启动DVM虚拟机 预加载部分资源,如一些通用类.通用资源.共享库等 启动syst ...

  3. c++builder启动了怎么停止_App 竟然是这样跑起来的 —— Android App/Activity 启动流程分析...

    在我的上一篇文章: AJie:按下电源键后竟然发生了这一幕 -- Android 系统启动流程分析​zhuanlan.zhihu.com 我们分析了系统在开机以后的一系列行为,其中最后一阶段 AMS( ...

  4. SpringBoot启动流程分析(四):IoC容器的初始化过程

    SpringBoot系列文章简介 SpringBoot源码阅读辅助篇: Spring IoC容器与应用上下文的设计与实现 SpringBoot启动流程源码分析: SpringBoot启动流程分析(一) ...

  5. Exynos4412 Uboot 移植(二)—— Uboot 启动流程分析

    uboot启动流程分析如下: 第一阶段: a -- 设置cpu工作模式为SVC模式 b -- 关闭中断,mmu,cache v -- 关看门狗 d -- 初始化内存,串口 e -- 设置栈 f -- ...

  6. bootloader启动流程分析

    bootloader启动流程分析 1.Bootloader的概念和作用 Bootloader是嵌入式系统的引导加载程序,它是系统上电后运行的第一段程序.在完成对系统的初始化任务之后,它会将Flash中 ...

  7. MyBatis启动流程分析

    目录 MyBatis简单介绍 启动流程分析 简单总结 附录 MyBatis内置别名转换 参考 MyBatis简单介绍 MyBatis是一个持久层框架,使用简单,学习成本较低.可以执行自己手写的SQL语 ...

  8. NameNode之启动流程分析

    NameNode启动流程分析 public staticvoid main(Stringargv[]) throws Exception { if (DFSUtil.parseHelpArgument ...

  9. springboot中获得app_Spring Boot 应用程序启动流程分析

    SpringBoot 有两个关键元素: @SpringBootApplication SpringApplication 以及 run() 方法 SpringApplication 这个类应该算是 S ...

最新文章

  1. java编程思想第四版第三章要点习题
  2. 为什么WEB-INF外的jsp无法根据cookie享受国际化
  3. python中ht表示什么_如何看待某国内大公司Python面试题,有关dict中初始化为固定值?...
  4. Log4j2突发重大漏洞
  5. sheet中没有getcolumns()方法吗_家庭亲子教育中的八种方法,你做到了吗?
  6. 010 Editor 8.0.1 之 逆向分析及注册机编写
  7. 提升自己的认知-思维模型
  8. 如何利用Python爬虫爬取小说网站并保存到txt文件
  9. JavaEE | 可变参数
  10. 前端面试题——计算机网络 高频
  11. windows 安装达梦数据库Python 报错:fatal error C1083: Cannot open include file: ‘DPI.h‘: No such file or direc
  12. swiper 在PC端使用禁止鼠标拖动
  13. OpenCV3入门(五)图像的阈值
  14. Android App开发学习第十四天:RecyclerView的简单使用
  15. 【转】Android权限获取机制与常见权限不足问题分析
  16. 两行代码隐藏进程在top中的显示
  17. 永辉超市第三季营收222亿:净亏7.8亿 卖金龙鱼股权套现1.7亿
  18. wireshark抓包常用命令
  19. 小米运动蓝牙耳机重新配对_小米运动蓝牙耳机怎么重置
  20. 函子, 适用函子和单子的Swift简单实现

热门文章

  1. windows 10设置host
  2. 谈谈你对Spring的理解?
  3. Altium Designer 20的中英文切换
  4. android设置录音权限设置,android录音权限提示体验,自认比较优雅的解决方法!
  5. 我靠这份阿里巴巴软件测试笔试题(附答案),成功入职阿里巴巴
  6. 计算机蓝屏原因原理,电脑蓝屏的正确处理方式
  7. window窗口运行机制
  8. 1 1同步练与测c语言,1+1同步练与测会计基础答案
  9. 灰度发布和蓝绿,发布更新部署
  10. QSettings使用笔记