Android显示系统(10)- SurfaceFlinger内部结构

一、前言:

之前讲述了native层如何使用SurfaceFlinger,我们只是看到了简单的API调用,从本文开始,我们逐步进行SurfaceFlinger内部结构的分析。话不多说,莱茨狗~

二、类图:

2.1、总体架构:

先看下SurfaceFlinger的关键成员和我们BootAnimation侧关键成员如何对应起来,这不是严格的UML类图,但是这么画我觉着很容易理解,就先这么画了。
在这里插入图片描述

可以看出:

  • SurfaceFlinger侧会为BootAnimation创建一个Client,其实,SF会为每个APP都创建一个Client;
  • SurfaceFlinger侧有一个BufferQueueLayer(Layer的子类)对应APP侧的SurfaceControl,允许有一个APP有多个Layer,同时,SF会生成多个SurfaceControl
  • BufferQueueLayer是一个buffer队列,队列有一个消费者mConsumer和一个生产者mProducer
  • APP侧的SurfaceControl当中有一个Surface
  • Surface当中又有一个数组mSlots表示64个buffer,对应SF当中其实也有这么一个数组,如果数组来管理这些buffer,这个是比较复杂的流程,后面单独写一篇文章介绍;

2.2、代理关系:

上面看到好多类似于SurfaceCompser的字眼,到底啥关系呢?我给你画个图:

在这里插入图片描述

熟悉Binder机制的朋友都应该能看懂,Bpxxxx一般就是代理类,Bnxxxx一般就是本地类,这样APP侧调用mClient就像调用Client一模一样的,底层Binder帮你处理了。一种RPC的思想。

三、APP连接SurfaceFlinger:

前面画了静态的类图,接下来我们看下APP如何去和SurfaceFlinger建立连接。

  1. APP侧获得SurfaceFlinger服务:

    • BootAnimation构造函数中,我们会通过mSession = new SurfaceComposerClient();来获取SF的代理类。

      BootAnimation::BootAnimation(sp<Callbacks> callbacks)
              : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
              mTimeFormat12Hour(false), mTimeCheckThread(nullptr), mCallbacks(callbacks) {
          // SurfaceFlinger在客户端的代理
          mSession = new SurfaceComposerClient();
          // 。。。删除非关键代码
      }
      
  2. 强引用SF服务:

    • 强引用时候就会执行SurfaceComposerClient::onFirstRef()

      void BootAnimation::onFirstRef() {
          // 将当前 BootAnimation 对象链接到图形服务的死亡通知。这意味着如果图形服务崩溃或退出,当前对象将收到通知。
          status_t err = mSession->linkToComposerDeath(this);
          if (err == NO_ERROR) {
              // 预加载开机动画文件
              preloadAnimation();
      		// 。。。
          }
      }
      
    • 里面会调用conn = sf->createConnection();这里面的sf表示SurfaceFlinger,调用这个方法就可以在SF当中创建一个Client了。

      void SurfaceComposerClient::onFirstRef() {
          sp<ISurfaceComposer> sf(ComposerService::getComposerService());
          if (sf != nullptr && mStatus == NO_INIT) {
              sp<ISurfaceComposerClient> conn;
              // 调用这句之后,SF侧会创建一个Client来对应APP
              conn = sf->createConnection();
              if (conn != nullptr) {
                  mClient = conn;
                  mStatus = NO_ERROR;
              }
          }
      }
      
    • BpSurfaceComposer当中发起Binder调用:

          virtual sp<ISurfaceComposerClient> createConnection()
          {
              Parcel data, reply;
              data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
              // 发起Binder调用
              remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
              return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
          }
      
    • SurfaceFlinger侧创建Client:

      SurfaceFlinger端通过onTransact收到CREATE_CONNECTION消息并处理:

      status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
                                          uint32_t flags) {
          status_t credentialCheck = CheckTransactCodeCredentials(code);
          if (credentialCheck != OK) {
              return credentialCheck;
          }
          // 调用了父类BnSurfaceComposer的方法去处理消息
          status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
          // ...
      }
      

      看到没有,转手就调用了父类的onTransact方法:

      status_t BnSurfaceComposer::onTransact(
          uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
      {
          switch(code) {
              case CREATE_CONNECTION: { // 处理链接,创建Client
                  CHECK_INTERFACE(ISurfaceComposer, data, reply);
                  sp<IBinder> b = IInterface::asBinder(createConnection());
                  reply->writeStrongBinder(b);
                  return NO_ERROR;
              }
              // 。。。
      	}
      	// 。。。
      }
      

      由于C++的多态性,父类指针指向子类对象,因此这个createConnection方法属于子类SurfaceFlinger的:

      sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
          return initClient(new Client(this));
      }
      

      至此,Client就创建好了。

四、总结:

本文主要讲了SurfaceFlinger内部几个非常重要的概念,并且,分析了APP和SurfaceFlinger建立连接的时候,SurfaceFlinger干了啥,后续再分析:如何获取画布,如何往画布上作图,如何提交已经做好图的画布,并且会专门分析buffer管理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/935381.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

源码编译安装MySQL

MySQL相应版本的tar包下载 在5.7的版本的MySQL编译安装的时候&#xff0c;需要依赖C语言的库文件【boost】&#xff0c; 如上图所示&#xff0c;如果你使用第一个MySQL的tar包&#xff0c;还需要去网上去下载boost即C语言的库文件&#xff0c;但是第二个tar包就既包含MySQL的源…

threejs 建筑设计(室内设计)软件 技术调研之一 画墙体

运用threejs 开发 建筑设计&#xff08;室内设计&#xff09;软件 技术调研 一 画墙体 实现功能&#xff1a; 左键点击开始画线&#xff0c;移动时下一端点跟随鼠标移动&#xff0c;产生活动的线&#xff0c;并标注线长&#xff0c;同时标注与前一段线的夹角。标注线和夹角分…

遗传算法与深度学习实战(27)——进化卷积神经网络

遗传算法与深度学习实战&#xff08;27&#xff09;——进化卷积神经网络 0. 前言1. 自定义交叉算子2. 自定义突变操作符3. 进化卷积神经网络小结系列链接 0. 前言 DEAP toolbox 中提供的标准遗传操作符对于自定义的网络架构基因序列来说是不够的。这是因为任何标准的交叉算子…

2024年第十五届蓝桥杯青少组C++国赛—割点

割点 题目描述 一张棋盘由n行 m 列的网格矩阵组成&#xff0c;每个网格中最多放一颗棋子。当前棋盘上已有若干棋子。所有水平方向或竖直方向上相邻的棋子属于同一连通块。 现给定棋盘上所有棋子的位置&#xff0c;如果要使棋盘上出现两个及以上的棋子连通块&#xff0c;请问…

嵌入式硬件-- 元器件焊接

1.锡膏的使用 锡膏要保存在冰箱里。 焊接排线端子&#xff1b;138度的低温锡&#xff08;锡膏&#xff09;&#xff0c; 第一次使用&#xff0c;直接拿东西挑一点涂在引脚上&#xff0c;不知道多少合适&#xff0c;加热台加热到260左右&#xff0c;放在上面观察锡融化&#…

Linux 简单命令总结

1. 简单命令 1.1. ls 列出该目录下的所有子目录与文件&#xff0c;后面还可以跟上一些选项 常用选项&#xff1a; ・-a 列出目录下的所有文件&#xff0c;包括以。开头的隐含文件。 ・-d 将目录象文件一样显示&#xff0c;而不是显示其下的文件。如&#xff1a;ls -d 指定目…

深入探讨可调电位器:原理、应用及编程实现

在电子电路和嵌入式系统中&#xff0c;可调电位器是一种常见且实用的元件&#xff0c;用于调节电压或电阻。无论是硬件设计还是控制系统开发&#xff0c;可调电位器都扮演着重要角色。本文将从可调电位器的工作原理、常见应用及其在C编程中的实际使用&#xff0c;帮助读者深入了…

MVC配置文件及位置

配置文件位置 默认位置 WEB-INF目录下&#xff0c;文件名&#xff1a;<servlet-name>-servlet.xml <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi"http://www.w3.…

26. Three.js案例-自定义多面体

26. Three.js案例-自定义多面体 实现效果 知识点 WebGLRenderer WebGLRenderer 是 Three.js 中用于渲染场景的主要类。它支持 WebGL 渲染&#xff0c;并提供了多种配置选项。 构造器 new THREE.WebGLRenderer(parameters) 参数类型描述parametersObject可选参数对象&…

Java_实例变量和局部变量及this关键字详解

最近得看看Java,想学一学Flink实时的东西了&#xff0c;当然Scala语法也有这样的规定&#xff0c;简单看一下这两个吧&#xff0c;都比较容易忽视 实例变量和局部变量 实例变量和局部变量是常见的两种变量类型&#xff0c;区别 作用域&#xff1a; 实例变量&#xff1a;实例变…

C++50道经典面试题

文章结尾有最新热度的文章,感兴趣的可以去看看。 本文是经过严格查阅相关权威文献和资料,形成的专业的可靠的内容。全文数据都有据可依,可回溯。特别申明:数据和资料已获得授权。本文内容,不涉及任何偏颇观点,用中立态度客观事实描述事情本身 导读 作为一种通用且面向对…

ansible自动化运维(三)jinja2模板roles角色管理

相关文章ansible自动化运维&#xff08;一&#xff09;简介及清单,模块-CSDN博客ansible自动化运维&#xff08;二&#xff09;playbook模式详解-CSDN博客ansible自动化运维&#xff08;四&#xff09;运维实战-CSDN博客 三.Ansible jinja2模板 Jinja2是Python的全功能模板引…

池化在深度学习中增强特征的作用

目录 ​编辑 引言 池化的基本作用与特征降维 池化的定义与目的 池化操作的实现 提取关键特征与计算效率的提升 池化对特征提取的影响 平均池化的应用 提高特征鲁棒性与过拟合的防止 池化对模型鲁棒性的贡献 池化防止过拟合的原理 增强多级特征与特征表达能力的提升…

【OJ题解】面试题三步问题

个人主页: 起名字真南的CSDN博客 个人专栏: 【数据结构初阶】 &#x1f4d8; 基础数据结构【C语言】 &#x1f4bb; C语言编程技巧【C】 &#x1f680; 进阶C【OJ题解】 &#x1f4dd; 题解精讲 目录 **题目链接****解题思路****1. 问题分析****2. 递归思路****3. 优化方案&a…

a few paper talked about software building process, so I learned

see also https://martinfowler.com/bliki/BlueGreenDeployment.html https://martinfowler.com/books/continuousDelivery.html https://martinfowler.com/articles/continuousIntegration.html https://swizec.com/blog/why-software-only-moves-forward/

Jenkins参数化构建详解(This project is parameterized)

本文详细介绍了Jenkins中不同类型的参数化构建方法&#xff0c;包括字符串、选项、多行文本、布尔值和git分支参数的配置&#xff0c;以及如何使用ActiveChoiceParameter实现动态获取参数选项。通过示例展示了传统方法和声明式pipeline的语法 文章目录 1. Jenkins的参数化构建1…

Tablesaw封装Plot.ly实现数据可视化

上文介绍tablesaw的数据处理功能&#xff0c;本文向你展示其数据可视化功能&#xff0c;并通过几个常用图表示例进行说明。 Plot.ly包装 可视化是数据分析的重要组成部分&#xff0c;无论你只是“查看”新数据集还是验证机器学习算法的结果。Tablesaw是一个开源、高性能的Java…

物流行业新突破:数字孪生的核心作用解析

在现代物流行业&#xff0c;效率和精准度是企业竞争的关键。随着数字化技术的发展&#xff0c;数字孪生作为一种新兴技术&#xff0c;正在智慧物流领域崭露头角。通过构建真实物流系统的虚拟映射&#xff0c;数字孪生帮助企业实现全方位的管理优化&#xff0c;为智慧物流带来了…

手机租赁系统开发全流程解析与实用指南

内容概要 在如今快速发展的科技时代&#xff0c;手机租赁系统已经成为一种新兴的商业模式&#xff0c;非常符合当下市场需求。那么&#xff0c;在开发这样一个系统的时候&#xff0c;首先要从需求分析和市场调研开始。在这一阶段&#xff0c;你需要了解用户需要什么&#xff0…

ViewModel

ViewMode是MVVM架构模式中VM层对应的类&#xff0c;它的作用是存储界面数据&#xff0c;并和界面发生数据交互。ViewModel能感知生命周期&#xff0c;并且在界面由于配置问题发生重建时候&#xff0c;可以保持当前的数据不变。生命周期如下&#xff1a; ViewMode由ViewModePr…