WMS帧缓冲区
屏幕刷新率(HZ):
代表屏幕在1秒内刷新的次数,Android手机一般是60Hz(也即是1s刷新60帧,大约16.67ms刷新1帧)
系统帧速率(FPS):
代表系统在1秒内合成的帧数,这个值的大小由系统算法和硬件决定.
分析屏幕卡顿的原因
当我们的系统帧速率跟不上屏幕刷新率的速度时,假如屏幕刷新率时候60HZ,但是系统帧速率是10PFS,也就是说屏幕原本1秒中可以刷新60帧,但是现在只提供给了10帧给屏幕刷新,就会造成刷新完10帧后,最终停留在第10帧画面上,1s-1s/6=5/6s的剩余时间都卡在了第10帧画面上,给用户带来的视觉体验就是卡顿.
VSync
全称是Vertical Synchronize,垂直同步,保证屏幕刷新率和系统帧速率一致性,防止卡顿、屏幕撕裂和丢帧.
扩展:
在显示当前这一帧数据的时候,会同时生成下一帧的数据;当显示下一帧数据的时候,直接把生成的数据拿来展示即可.
GPU作用举例
- 将颜色值(如:#FF000000)转换成屏幕LED灯可以可以识别的红、绿、蓝RGB色值
- 将我们的图像进行放大和缩小
SurfaceFlinger
负责图像的合成.
一个Window对应3个Buffer缓冲(比如:Navigation导航栏、StatusBar状态栏和我们的应用程序窗口都分别表示一个Window),一个Window表示一个Surface,由SurfaceFlinger将我们的一个个Surface合成,然后在通过HWC(Hardware Compose)经过硬件合成或者软件整体合成,最终构成了我们整个手机屏幕.
- 一个Window有三个Buffer的好处:
- 复用
- 减少资源浪费
- 整体流程
每一个Window(比如:Navigation导航栏)都对应一个Surface,而一个Suface对应SurfaceFlinger中的一个图层(BufferQueueLayer),一个图层(BufferQueueLayer)中包含了生产者、BufferQueue和消费者,通过生产者将Surface写入BufferQueue,然后通过消费者从BufferQueue中读出数据,通过HWC硬件设备经过硬件合成或者是软件合成称为我们的图像,然后将合成的图像展示在手机屏幕上.
- BufferQueue
BufferQueue里面了一个BufferQueueCore,而BufferQueueCore包含了一个个卡槽(BufferSlot),一个BufferQueue最多可以包含64个卡槽,每一个卡槽BufferSlot包含了Buffer的状态mBufferState,Buffer包含了如下4中状态:
- Free:可被上层使用
- Dequeue:出列,正在被上层使用
- Queued:入列,已完成上层绘制,等待SurfaceFlinger绘制
- Acquired:被获取,SurfaceFlinger正持有该Buffer进行合成
状态的变化:
Free->Dequeued->Queued->Acquired->Free
- Surface
Surface包含了lockCanvas和unlockCanvasAndPost(canvas)方法,分别对应了dequeue出列和queue入列两种状态,lockCanvas方法会返回一个Canvas画布对象,接着调用我们View的draw方法通过拿到的Canvas进行View的绘制,绘制完成后,交给unlockCanvasAndPost方法进行处理,处理完成后,再将我们的数据通过生产者添加到BufferQueue队列中去.
面试题
- 什么是SurfaceView?
是一个View控件,他单独拥有一个画布Canvas,正常情况下是一个窗口Window(比如:我们的应用程序窗口,也就是是一个Activity中的PhoneWindow窗口)拥有一个画布Canvas;而SurfaceView这个View却拥有一个Canvas画布对象,我们可以通过lockCanvas获取到这个Canvas画布对象,然后通过这个画布对象进行View绘制,绘制完成后调用unlockCanvasAndPost方法,将绘制后的数据写入到BufferQueue队列,然后通过SufaceFlinger组合Surface给HWC合成图像交给屏幕展示.
我们可以把SurfaceView理解成是一个精简版的窗口Window;他可以同时在主线程和子线程中刷新UI.
使用场景:
摄像、播放视频、帧动画的优化等.
- View和SurfaceView的区别?
- View是属于一个Window的(一个Window中可以包含很多的View),一个Window对应了一个Surface,也就是一个Window中的所有View公用一个Surface的画布对象;而SurfaceView单独拥有一个Surface的画布对象.
因此,SurfaceView拥有更高的效率.- 正常情况下,View只能在主线程中更新UI,而SurfaceView可以同时在主线程和子线程中更新UI.
- 正常情况下,View的屏幕刷新率是60HZ,但是SurfaceView可以更高屏幕的刷新率,可以增大屏幕刷新率的值.
因此,SurfaceView可以通过更改屏幕刷新率,让屏幕的画面更流畅.
- 应用程序是如何与SurfaceFlinger进行通信的,View的绘制是如何把数据传递给SurfaceFlinger的?
- 首先,我们通过Surface的lockCanvas()方法,通过生产者从SurfaceFling中的缓冲队列(BufferQueue)中拿到数据,数据会被转换成Canvas画布对象;
- 然后调用View的draw方法通过拿到Canvas画布对象进行View的绘制,绘制完成后,调用Surface的unlockCanvasAndPost(canvas)方法,通过生产者将绘制后的数据,添加到缓冲队列(BufferQueue)中去.
- relayout是如何向SurfaceFlinger申请Surface的?
App进程:
ViewRootImpl.performTranversal()
->ViewRootImpl.relayoutWindow()
->mWindowSession.relayout(…,mSurface)SystemServer进程的WMS服务:
WindowManagerService.relayoutWindow()
->createSurfaceControl(Surface outSurface)
->winAnimator.createSurfaceLocked
->mSurfaceControl.Builder.build()
->new SurfaceControl()
->nativeCreate()
->SurfaceComposerClient::createSurfaceChecked(…,&surface,…)SurfaceFlinger进程:
Client::createSurface
->mFlinger->createLayerSystemServer进程的WMS服务:
surfaceControl.getSurface(outSurface) @WindowManagerService.java
->outSurface.copyFrom(mSurfaceControl)App进程:
ViewRootImpl.relayoutWindow()//这个时候App就可以拿到创建的Surface.