android 13/14高版本SurfaceFlinger出现VSYNC-app/VSYNC-appSf/VSYNC-sf剖析

问题背景:

了解surfaceflinger的vsync同学都可能知道vsync属于一个节拍器,主要用来控制有节奏的渲染,不至于会产生什么画面撕裂等现象。
一般vsync都有会有2部分:
app部分vsync,控制各个app可以有节奏的上帧
surfaceflinger部分vsync,控制surfaceflinger的一个合成画面送显示的节奏

上面2部分其实大家了解vsync都知道,但是近期再看android 13的surfaceflinger trace时候发现有如下情况:

老版本:
systrace查看发现老版本其实只有app和sf的VSYNC情况
在这里插入图片描述

新版本
systrace出现了3个,多了一个VSYNC-appSf:
在这里插入图片描述

这个地方就有学员朋友在群里问这个问题,刚好我近期也在修炼surfaceflinger相关,针对这个问题,其实大部分人我估计态度都是忽略哈,,网上也基本找不到答案,哪怕问人也很难问到哈。
那么这个VSYNC-appSf到底是啥,为啥老版本没有新版本会有这个?这个就是本blog要讲解的重点 。

更多framework干货课程优惠获取相关可以+V(androidframework007)
视频:https://www.bilibili.com/video/BV1ah411d7Y3
在这里插入图片描述

线索追踪及官方解释

在对appSf的修改进行git log追踪时候发现有如下一个commit,这个commit有专门写明原因哈:

appSf产生原因,官方解释:

SurfaceFlinger: decouple EventThread from SF wakeupToday we have two instances of EventThread:1. 'app' - used to wake up Choreographer clients2. 'sf' - used to wake up SF mian thead *and*Choreographer clients that uses sf instanceNow this creates an ambiguity when trying to reason about the expectedvsync time and deadline of 'sf' EventThread:- SF wakes up sfWorkDuration before a vsync and targets that vsync- Choreographer users wakes up with SF main thread but targets thevsync that happens after the next SF wakeup.To resolve this ambiguity we are decoupling SF wakeup from 'sf'EventThread. This means that Choreographer clients that uses 'sf'instance will keep using the EventThread but SF will be waking updirectly by a callback with VSyncDispatch. This allows us to correctthe expected vsync and deadline for both.Test: Interacting with the device and observe systracesTest: new unit test added to SF suiteBug: 166302754Change-Id: I76d154029b4bc1902198074c33d38ff030c4601b

不过比较遗憾哈,全是英文的,这个要看懂可能不难哈,但是要完全领悟贯通那就要很了解surfaceflinger的vsync了。不然那就只能停留在字面意思啦,根本无法理解精华。
下面马哥带大家来理解一下吧,都把相关翻译写下来啦,不一定全对哈。
带马哥注释理解

  SurfaceFlinger: decouple EventThread from SF wakeup//标题就是把EventThread分离出sf,大概意思就是不想让EventThread管sf相关vsyncToday we have two instances of EventThread://这个是解释修改前的现状和背景,目前有两个EventThread实例,一个app一个sf1. 'app' - used to wake up Choreographer clients //app的EventThread属于用来唤醒app端2. 'sf' - used to wake up SF mian thead *and* Choreographer clients that uses sf instance//sf的EventThread有2个责任,一个是自己来唤醒Sf的主线程,另一个也是关键一点,有对应的clients端也需要使用//下面讲述修改背景,本质就是说sf的EventThread因为有2个责任,一个是自己sf的唤醒,一个是client端唤醒,二者共用情况,可能会有时候排查vsync会有模棱两可的情况,即没办法准确确认vsync问题原因Now this creates an ambiguity when trying to reason about the expectedvsync time and deadline of 'sf' EventThread:- SF wakes up sfWorkDuration before a vsync and targets that vsync- Choreographer users wakes up with SF main thread but targets thevsync that happens after the next SF wakeup.//为了解决这类可能导致模棱两可的情况,那么就需要吧sf的EventThread进行相关的分离,sf原本负责的2个功能拆开,把sf自己唤醒自己的转移到了直接让VSyncDispatch进行callback调用,另一个对于client端的功能就保留在EventThread中,这样就不会造成上面的模棱两可疑惑。也就是我们看到的会多了一个appSfTo resolve this ambiguity we are decoupling SF wakeup from 'sf'EventThread. This means that Choreographer clients that uses 'sf'instance will keep using the EventThread but SF will be waking updirectly by a callback with VSyncDispatch. This allows us to correctthe expected vsync and deadline for both.Test: Interacting with the device and observe systracesTest: new unit test added to SF suiteBug: 166302754Change-Id: I76d154029b4bc1902198074c33d38ff030c4601b

总结一下:
简单说就是吧以前的sf的EventTread功能中,自己唤醒触发vsync的部分移除EventTread,让VSyncDispatch直接进行(后面有机会讲解vsync再深入分析),不在使用EventThread来搞对于的sf的vsync了。
但是sf还有一个功能就是对待客户端的,这个部分保留在EventTread中,变成我们看到的appSf

哈其实你是不是有点懂又还是没彻底领悟,特别是为啥sf还有两个功能?以前不是说了只是来产生sf的vsync么?正常哈,因为上面的结论其实都是相当于一个结论哈,要彻底理解还需要其他相关的补充哈。

千里马实战解读理解appSf

理解sf为啥会有两个功能,以前不是只有一个产生sf端的vsync么?
我们注意看看人家的解释哈:

1. 'app' - used to wake up Choreographer clients 
2. 'sf' - used to wake up SF mian thead *and* Choreographer clients that uses sf instance

sf另一个功能是 Choreographer clients 需要使用这个sf的EventThread,这里应该是大家最不可以理解的地方。这里看看上面的app也是用的Choreographer clients ,表面意识就是Choreographer的客户端,其实就是各个需要上帧的应用的Choreographer客户端。
那么这里说的 Choreographer clients that uses sf instance,难道是sf的也有对于的客户端吗?Choreographer也有直接指定sf这个EventTread线程的?哈哈其实确实有的具体可以看以下代码:

    private Choreographer(Looper looper, int vsyncSource) {mLooper = looper;mHandler = new FrameHandler(looper);mDisplayEventReceiver = USE_VSYNC? new FrameDisplayEventReceiver(looper, vsyncSource): null;mLastFrameTimeNanos = Long.MIN_VALUE;mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());mCallbackQueues = new CallbackQueue[CALLBACK_LAST + 1];for (int i = 0; i <= CALLBACK_LAST; i++) {mCallbackQueues[i] = new CallbackQueue();}// b/68769804: For low FPS experiments.setFPSDivisor(SystemProperties.getInt(ThreadedRenderer.DEBUG_FPS_DIVISOR, 1));}

大家注意没有这个Choreographer构造时候就有个vsyncSource,这个是不是大家都没有注意过哈,它到底有哪些值呢?

  /*** When retrieving vsync events, this specifies that the vsync event should happen at the normal* vsync-app tick.* <p>* Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h*/public static final int VSYNC_SOURCE_APP = 0;/*** When retrieving vsync events, this specifies that the vsync event should happen whenever* Surface Flinger is processing a frame.* <p>* Needs to be kept in sync with frameworks/native/include/gui/ISurfaceComposer.h*/public static final int VSYNC_SOURCE_SURFACE_FLINGER = 1;

可以看到有两个
一个最常见的的app
另一个就是sf的
sf这个,也就是app端可以指定vsync是跟随surfaceflinger的合成vsync的,所以这里也就是被叫做Choreographer clients ,这里大家就可以理解了吧,具体有没有谁使用呢?
可以看看有谁使用Choreographer getSfInstance方法:
在这里插入图片描述

可以看到还是有一些场景就是使用的sf的vsync,自然使用vsync就会涉及到回调获取vsync和请求vsync。所以这里就是上面的说的client可能会使用相关的sf vsync情况,sf自身也有请求获取情况,所以这个两个业务混一起了,那确实有时候一些问题就不好排查了。

结合systrace验证

1、确定是不是真的有有clinet链接到了sf的EventThread
这个其实可以通过相关的dumpsys SurfaceFlinger来实现,看看是否appSf是否有对于的connection,不过比较遗憾哈,默认的dumpsys并没有吧appSf的EventThread打印,只打印了app的EventTread,所以这里就需要我们修改一下相关dumpsys如下:

test@test:~/nx563j_xiaomi/frameworks/native/services$ git diff surfaceflinger/SurfaceFlinger.cpp
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b1b31bbd76..04f5b63dc0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -5180,6 +5180,7 @@ void SurfaceFlinger::dumpVSync(std::string& result) const {mDebugDisplayModeSetByBackdoor ? "yes" : "no");mScheduler->dump(mAppConnectionHandle, result);
+    mScheduler->dump(mSfConnectionHandle, result);//加入一行吧appSf相关EventTread信息也打一下mScheduler->dumpVsync(result);StringAppendF(&result, "mHWCVsyncPendingState=%s mLastHWCVsyncState=%s\n",to_string(mHWCVsyncPendingState).c_str(), to_string(mLastHWCVsyncState).c_str());

结果如下:

app: state=Idle VSyncState={displayId=0, count=548}//正常只有这个打印pending events (count=0):connections (count=16):Connection{0x747b86b730, VSyncRequest::None,1000}Connection{0x747b879e30, VSyncRequest::None,1000}Connection{0x747b86ffd0, VSyncRequest::None,1000}Connection{0x747b8784d0, VSyncRequest::None,1000}Connection{0x747b86c1b0, VSyncRequest::None,10110}Connection{0x747b8856d0, VSyncRequest::None,10110}Connection{0x747b882db0, VSyncRequest::None,10110}Connection{0x747b87fd90, VSyncRequest::None,10110}Connection{0x747b8839f0, VSyncRequest::None,10111}Connection{0x747b883bb0, VSyncRequest::None,1000}Connection{0x747b8728f0, VSyncRequest::None,1000}Connection{0x747b870350, VSyncRequest::None,10111}Connection{0x747b882870, VSyncRequest::None,10142}Connection{0x747b880570, VSyncRequest::None,10144}Connection{0x747b871150, VSyncRequest::None,10144}Connection{0x747b86da30, VSyncRequest::None,10141}
appSf: state=Idle VSyncState={displayId=0, count=165}//额外加上这个打印pending events (count=0):connections (count=4)://client链接数量Connection{0x747b86ca70, VSyncRequest::None,1000}Connection{0x747b8833d0, VSyncRequest::None,1000}Connection{0x747b877190, VSyncRequest::None,1000}Connection{0x747b87cc90, VSyncRequest::None,10110}
VsyncController:

发现确实appSf也有4个链接,uid 1000是system和10110 是systemui

结合trace打印查看appSf相关的:

回想一下app端如果要请求vsync时候最后是跨进程调用到了如下代码:

frameworks/native/services/surfaceflinger/Scheduler/EventThread.cpp

binder::Status EventThreadConnection::requestNextVsync() {ATRACE_CALL();mEventThread->requestNextVsync(this);return binder::Status::ok();
}

这里trace中只有个方法的输出,这里可以添加一下,用来区分app还是appSf的EventTread,修改如下:

 std::string toString(const DisplayEventReceiver::Event& event) {
@@ -194,7 +194,10 @@ binder::Status EventThreadConnection::setVsyncRate(int rate) {binder::Status EventThreadConnection::requestNextVsync() {ATRACE_CALL();
+    ATRACE_BEGIN(((impl::EventThread*)mEventThread)->toNameString());//主要线程名字打出到Trace中
+    ALOGE(" EventThreadConnection::requestNextVsync() threadName %s calluid %d",((impl::EventThread*)mEventThread)->toNameString(),(int)mOwnerUid);mEventThread->requestNextVsync(this);
+        ATRACE_END();return binder::Status::ok();}

然后再看trace情况如下:
看sf的clinet端请求vsync
在这里插入图片描述
这里因为tag太小做个标记方便寻找
下面来看具体的apSf的vsync到来

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

UVM-什么是UVM方法学

概念简介 百度对UVM的解释如下&#xff1a; 通用验证方法学&#xff08;Universal Verification Methodology, UVM&#xff09;是一个以SystemVerilog类库为主体的验证平台开发框架&#xff0c;验证工程师可以利用其可重用组件构建具有标准化层次结构和接口的功能验证环境 UVM…

UE4 AI群集实现

逻辑就不用说了&#xff0c;就是计算对应图形位置让每个Pawn移动到该位置 因为有时候AI与AI会卡住 所以加上这个Bool为true&#xff0c;以及设置两个AI之间至少隔的距离&#xff0c;设置在一个合理的参数即可 有时候AI群集&#xff0c;AI与AI会比较紧密&#xff0c;可以将Caps…

初始 c++(1)

目录: 目录 1: 命名空间的详解 2:c的输入与输出关键字及理解 3:详细讲解第一个c程序(每段代码的意思) 4:缺省参数的理解 5:函数重载 引言&#xff1a;从今天开始我们就开始学习c了&#xff0c;让我们一起开始新的知识吧&#xff01; 1&#xff1a;命名空间 所谓的命名空间…

分类预测 | MATLAB实现SSA-CNN-LSTM-Attention数据分类预测(SE注意力机制)

分类预测 | MATLAB实现SSA-CNN-LSTM-Attention数据分类预测&#xff08;SE注意力机制&#xff09; 目录 分类预测 | MATLAB实现SSA-CNN-LSTM-Attention数据分类预测&#xff08;SE注意力机制&#xff09;分类效果基本描述模型描述程序设计参考资料 分类效果 基本描述 1.MATLAB实…

用 pytorch 训练端对端验证码识别神经网络并进行 C++ 移植

文章目录 前言安装安装 pytorch安装 libtorch安装 opencv&#xff08;C&#xff09; 准备数据集获取训练数据下载标定 编码预分析 数据集封装格式 神经网络搭建神经网络训练神经网络测试神经网络预测C 移植模型转换通过跟踪转换为 Torch Script通过注解转换为 Torch Script 编写…

数据结构 排序

数据结构 排序 文章目录 数据结构 排序1. 排序的概念及引用1.1 排序的概念1.2 常见的排序算法 2.常见排序算法的实现2.1 插入排序2.1.1 基本思想2.1.2 直接插入排序2.1.3 希尔排序(缩小增量排序) 2.2 选择排序2.2.1 基本思想2.2.2 直接选择排序2.2.3 堆排序 2.3 交换排序2.3.1 …

Java后端模拟面试 题集④

1.你先作个自我介绍吧 面试官您好&#xff0c;我叫张睿超&#xff0c;来自湖南长沙&#xff0c;大学毕业于湖南农业大学&#xff0c;是一名智能科学与技术专业的统招一本本科生。今天主要过来面试贵公司的Java后端开发工程师岗位。 大学里面主修的课程是Java、Python、数字图…

使用QT实现http里面的get和post

#1024程序员节&#xff5c;参与投稿&#xff0c;赢限定勋章和专属大奖# #假如你有一台服务器&#xff0c;你最想做哪些事&#xff1f;# #你被什么样的BUG困扰过一周以上&#xff1f;# 在http里面下面这些方法和服务器的响应代码一起用于HTTP协议中的请求和响应交互。请注意&…

Spring Boot + EasyUI 创建第一个项目(一)

创建一个Spring Boot和EasyUI相结合的项目。 一、构建一个Spring Boot项目 Spring Boot之创建一个Spring Boot项目&#xff08;一&#xff09;-CSDN博客 二、配置Thymeleaf Spring Boot Thymeleaf&#xff08;十一&#xff09;_thymeleaf 设置字体_人……杰的博客-CSDN博客…

mybatisplus开启sql打印的三种方式

1、在application.yml文件中添加mybatisplus的配置文件 使用mybatisplus自带的log-impl配置&#xff0c;可以在控制台打印出sql语句、执行结果的数据集、数据结果条数等详细信息&#xff0c;这种方法适合再调试的时候使用&#xff0c;因为这个展示的信息详细&#xff0c;更便于…

【算法练习Day25】 重新安排行程N 皇后 解数独

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 重新安排行程N 皇后解数独总…

C# Socket通信从入门到精通(2)——多个同步TCP客户端C#代码实现

前言: 我们在开发Tcp客户端程序的时候,有时候在同一个软件上我们要连接多个服务器,这时候我们开发的一个客户端就不够使用了,这时候就需要我们开发出来的软件要支持连接多个服务器,最好是数量没有限制,这样我们就能应对任意数量的服务器连接,由于我们开发的Tcp客户端程…

使用 Visual Studio Code (VS Code) 作为 Visual C++ 6.0 (VC6) 的编辑器

使用 Visual Studio Code (VS Code) 作为 Visual C 6.0 (VC6) 的编辑器 由于一些众所周知的原因&#xff0c;我们不得不使用经典&#xff08;过时&#xff09;的比我们年龄还大的已有 25 年历史的 VC 6.0 来学习 C 语言。而对于现在来说&#xff0c;这个经典的 IDE 过于简陋&a…

Leetcode1833. 雪糕的最大数量

Every day a Leetcode 题目来源&#xff1a;1833. 雪糕的最大数量 解法1&#xff1a;贪心 排序 本题唯一的难点在于计数排序。 计数排序详解&#xff1a;C算法之计数排序 为了尽可能多的买到雪糕&#xff0c;我们选择从价格低的雪糕开始买&#xff0c;统计能够买到的雪糕…

Java学习_day03_变量数据类型运算符

文章目录 变量定义声明赋值使用简化 数据类型基本数据类型整型浮点型布尔型字符型空型 引用数据类型数据类型转换自动类型转换强制类型转换 运算符算术运算符赋值运算符比较运算符逻辑运算符位运算符条件运算符一元运算符二元运算符三元运算符运算符优先级 变量 变量类似于数学…

计算机算法分析与设计(12)---贪心算法(最优装载问题和哈夫曼编码问题)

文章目录 一、最优装载问题1.1 问题表述1.2 代码编写 二、哈夫曼编码2.1 哈夫曼编码概述2.2 前缀码2.3 问题描述2.4 代码思路2.5 代码编写 一、最优装载问题 1.1 问题表述 1. 有一批集装箱要装上一艘载重量为 c c c 的轮船&#xff0c;已知集装箱 i ( 1 ≤ i ≤ n ) i(1≤i≤…

昇腾CANN 7.0 黑科技:大模型训练性能优化之道

目前&#xff0c;大模型凭借超强的学习能力&#xff0c;已经在搜索、推荐、智能交互、AIGC、生产流程变革、产业提效等场景表现出巨大的潜力。大模型经过海量数据的预训练&#xff0c;通常具有良好的通用性和泛化性。用户基于“大模型预训练微调”开发范式即可在实际业务场景取…

MySQL——练习

MySQL 一、练习要求二、练习过程 一、练习要求 创建表并插入数据&#xff1a; 字段名数据类型主键外键非空唯一自增idINT是否是是否nameVARCHAR(50)否否是否否glassVARCHAR(50)否否是否否 sch 表内容 id name glass 1 xiaommg glass 1 2 xiaojun glass 21、创建一个可以统计…

PostgreSQL与MySQL数据库对比:适用场景和选择指南

数据库是现代应用程序的基石之一&#xff0c;而在选择合适的数据库管理系统&#xff08;DBMS&#xff09;时&#xff0c;开发者常常会面临着许多选择。在这方面&#xff0c;PostgreSQL和MySQL是两个备受瞩目的选项。本文将深入研究这两者之间的异同&#xff0c;并为您提供适用场…

【使用OpenCV进行目标分割与计数的代码实例详解】

文章目录 概要实例一&#xff1a;硬币分割计数实例二&#xff1a;玉米粒分割计数 概要 在当今数字图像处理领域&#xff0c;图像分割技术是一项至关重要的任务。图像分割旨在将图像中的不同目标或区域准确地分开&#xff0c;为计算机视觉、图像识别和机器学习等领域提供了坚实…