Android卡顿原理分析和SurfaceFlinger,Surface概念简述

版权声明:本文为博主原创文章,转载希望能注明出处,感谢。 https://blog.csdn.net/u010126792/article/details/86236284

本篇仅是简述,还在学习中,后续会慢慢完善。

Android 卡顿原理

Android早期相较于IOS卡顿较为严重,从4.4开始,特别是5.0版本以后,由于各方面的优化(系统的和CPU,GPU,内存的),系统的流畅程度已经有了很大提升。
其中Vsync的持续改进起到了一定的作用,Vsync称为垂直同步主要是为了解决显卡生成帧的速度和屏幕(显示系统的一种)刷新的频率不一致,也就是CPU,GPU处理准备画面的频率和Display设备刷新频率(一般是16ms)不一致的问题,有了Vsync可以让显示器输出稳定正确的画面。
如果 CPU、GPU 处理,生成帧的速度和 Display 刷新的速度不一致,在不使用vsync的情况下会出现屏幕正在刷新第二帧图像,但是显卡已经更新了第三帧图像,这时反映到屏幕上就会产生一部分是第二帧的图像,一部分是第三帧的图像(画面撕裂(screentearing))。有了vsync机制,每次屏幕刷新时通过Vsync通知更新帧,这样显示的画面就不会出现上面的问题。Vsync可以由硬件或者软件生成。

Display 是Android 对输出显示设备的一个抽象,一般指手机显示器,在Andrid 4.1 后优化SurfaceFlinger,支持更多外部输入设备,比如HDMI, Wifi Display 等等。Display的输入是过滤后的所有Window的Surface, 输出是和显示设备尺寸相同的Buffer, 这个Buffer 最终送到了硬件的FB设备,或者HDMI设备,或者远处的Wifi Display Sink设备进行显示。输入到输出这条路径上有SurfaceFlinger, OpenGL 和 HWComposer。

不使用Vsync:
在这里插入图片描述
display展示第0帧的时候,GPU或者CPU准备第1帧显示的图片,第0帧结束时VSync信号到来,CPU或者GPU应该开始准备第2帧,但由于某些原因没有在Vsync处开始准备第二帧图像,Display再次展示时只能显示前一帧图像,反映到界面上会给用户卡顿的印象。

使用vsync:
在这里插入图片描述

上面的图展示了使用Vsync时的正常情况,但是还有一种情况是cpu,gpu在vsync到来时开始工作,但是可能由于CPU或者gpu工作太繁重,导致cpu,gpu忙不过来,处理合成surface的时间会变长,也会导致不能按时处理完下一帧图片。
CPU,gpu忙不过来的情况:
在这里插入图片描述
Display显示第0帧数据,CPU和GPU开始渲染第1帧画面,下一次Vsync到来之前完成了渲染,Display在第1个VSync后,正常显示第1帧;接着由于某些原因,cpu,gpu由于过忙没有及时地开始处理第2帧,VSync再次来时,由于第2帧数据还没有准备就绪,显示的还是第1帧,被Android开发组命名为“Jank”,当第2帧数据准备完成后,它并不会马上被显示,而是要等待下一个VSync。屏幕多显示了一次第1帧,如果频繁发生会导致卡顿。

为提高android的处理帧的效率,Android还提供了双缓冲,三缓冲方案:
在这里插入图片描述
缓冲区是构建和存储帧的容器,Android的双缓冲模型中,一个缓存区显示1帧,而在另一个缓存区进行下一帧的处理。如上图缓冲器标记为“A”和“B”。当显示缓冲区A时,系统开始在缓冲区B中建立一个新帧,当准备好时,它们交换缓冲区,B被显示,并且A中的帧被清除并且处理新的帧。除此之外还有三缓冲结构等等,具体的我也没太研究所以还需要大家自己去看。

Android 系统每 16ms(更准确的是大概16.6ms) 就会发出一次 VSYNC信号触发ui更新。屏幕一秒大约刷新60次,所里处理合称一帧花费的时间在 16ms 内,画面会比较流畅。
如果在16ms内由于view的绘制逻辑过于复杂,就会导致本次绘制新内容不会成功,依然会显示上次绘制的内容,如果频繁发生16ms无法完成界面更新的问题,反映到软件影响是看着应用的界面会感觉卡顿。

SurfaceFlinger 简述

来自:http://www.cnblogs.com/samchen2009/p/3364327.html
SurfaceFlinger的作用主要是merge Surface,用于接受多个来源的图形显示数据,然后将他们合称发送到显示设备。

SurfaceFlinger 是一个独立的Service, 它接收所有Window的Surface作为输入,根据ZOrder, 透明度,大小,位置等参数,计算出每个Surface在最终合成图像中的位置,然后交由HWComposer或OpenGL生成最终的显示Buffer, 然后显示到特定的显示设备上。

在Android底层绘制系统中,SurfaceFlinger 为App进程创建具体的Surface, 在SurfaceFlinger里对应成Layer, 然后负责管理、合成显示。Layer是SurfaceFlinger 进行合成的基本操作单元。Layer是在应用请求创建Surface的时候在SurfaceFlinger内部创建,因此一个Surface对应一个 Layer, 但注意,Surface不一定对应于Window,Android中有些Surface并不跟某个Window相关,而是有程序直接创建,比如说 StrictMode, 一块红色的背景,用于提示示Java代码中的一些异常, 还有SurfaceView, 用于显示有硬件输出的视频内容等。

Surface 概述

Window在android不同地方有不同含义,这里主要讨论WindowManagerService中管理的Window。Window 是 Android 中窗口的宏观定义,主要是管理 View 的创建,以及与 ViewRootImpl 的交互,将 Activity 与 View 解耦。

看下图:
在这里插入图片描述

Surface的创建由谁发起呢,App要显示自己的内容,会发起Surface创建请求,WindowManagerService, 负责接收APP请求,向SurfaceFlinger发起具体的请求创建Surface。Window与Surface一一对应。 Surface负责记录每个时刻Window的内容。在Android的SurfaceFlinger实现里,通常一个Surface有两块 Buffer, 一块用于绘画,一块用于显示,两个Buffer按照固定的频率进行交换,从而实现Window的动态刷新。

一个窗口界面包含多个View组成View hierachy的树形结构,只有最顶层的DecorView才对WMS可见,这个DecorView在WMS中有一个对应的WindowState,在SurfaceFlinger有对应的Layer。

Layer是SurfaceFlinger 进行合成的基本操作单元。Layer在应用请求创建Surface的时候在SurfaceFlinger内部创建,因此一个Surface对应一个 Layer, 但注意,Surface不一定对应于Window,Android中有些Surface并不跟某个Window相关,而是有程序直接创建,例如SurfaceView, 用于显示有硬件输出的视频内容等。

一个应用程序有多个窗口界面(Activity),可以包含多个Surface,每个window又对应一个Surface,Display每次显示的是多个Window融合后的效果。Surface内部对应一块屏幕缓冲区,窗口中所有的View共享一块缓冲区,所以窗口中的任何view最终都是绘制在Surface对应的buffer(屏幕缓冲区)上的。Android的View必须在主线程更新,是由于窗口中所有的View共享一块缓冲区,如果异步可更新,会造成数据的不同步。
Handle onto a raw buffer that is being managed by the screen compositor.
Surface持有一个被屏幕合成器管理的原始缓冲区,所以所有绘制的内容最终都会保存到这个缓冲区中。

Surface定义在ViewRootImpl中的成员,定义时已经实例化了:
final Surface mSurface = new Surface();
ViewRootImpl的个数与addView的调用次数相关,一个Activity可以多次调用addView, 也就是说一个Activity可以有多个Surface.
Surface 内部持有一个Canvas,可以利用这个Canvas绘制。

猜你喜欢

转载自blog.csdn.net/u010126792/article/details/86236284