关于图形显示部分可以参考官网:Graphics
图像显示原理
Linux
通常使用Framebuffer
来用作显示输出(Framebuffer
知识详解在这里),Framebuffer
就是一块内存区域,它通常是显示驱动的内部缓冲区在内存中的映射。
一旦用户进程把图像数据复制到Framebuffer
中,显示驱动会一个像素一个像素地扫描整个Framebuffer
,并根据其中的值更新屏幕上像素点的颜色。
驱动中这个更新屏幕的动作是固定的,它的周期就是我们常说的刷新率
Android
关于图像渲染显示的架构图如下:
结合这张图,我们需要重点关注的是:
-
Native Framework
中的Surface
- 无论开发者使用什么渲染
API
,一切内容都会渲染到Surface
上 Surface
中会关联一个BufferQueue
用于提供图像数据缓存- 大多数客户端使用
OpenGL ES
或Vulkan
渲染到Surface
- 有些客户端使用
Canvas
渲染到Surface
- 无论开发者使用什么渲染
-
Image Stream Producer
的定义是能够生成图形缓冲区以供消耗的任何对象。每个Producer
都会关联一个Surface
,例如Canvas 2D
:Java
层主要是通过View
中创建的Surface
对象来进行操作- 该
Surface
对象会与SurfaceFlinger
进行关联,并通过lockCanavas()
接口获取Canvas
对象 lockCanvas()
会将CPU渲染程序
连接到BufferQueue
的生产方,直到Surface
被销毁时才会断开连接
- 该
mediaserver视频解码器
:通过MediaPlayer
的setSurfaceHolder()
接口与SurfaceView
中的Surface
进行绑定
-
对于
Image Stream Consumer
来说,主要是SurfaceFlinger
,该系统服务会消耗当前可见的Surface
,并使用WindowManager
中提供的信息将它们合成到显示部分。SurfaceFlinger
是可以修改所显示部分内容的唯一服务。SurfaceFlinger
使用OpenGL
和Hardware Composer
来合成一组Surface
。- 当应用进入前台时,它会从
WindowManager
请求缓冲区。然后,WindowManager
会从SurfaceFlinger
请求layer
。layer
是surface
(包含BufferQueue
)和SurfaceControl
(包含屏幕框架等层元数据)的组合。
SurfaceFlinger
创建layer
并将其发送至WindowManager
。- 然后,
WindowManager
将Surface
发送至应用,但会保留SurfaceControl
来操控应用在屏幕上的外观。
-
Window Positioning
中的WindowManager
主要是用来控制Window
对象Window
对象是用来存放View
对象的容器,每个Window
对象都会关联Surface
对象WindowManager
监视Window
对象的生命周期、输入和焦点事件、屏幕方向、转换、动画、位置、变换、z顺序等- 然后将所有
Window
元数据发送给SurfaceFlinger
,SurfaceFlinger
利用这些元数据把自己管理的所有Surface
组合成layer
- 然后交给
Hardware Composer
做进一步处理
-
HAL
层中的Hardware Composer(HWC)
会根据当前硬件来进一步进行缓冲区的组合,它的具体实现依赖于特定的显示设备- 官网关于
HWC
的数据流如下:
SurfaceFlinger
作为client
向HWC
提供一个完整的layer
列表,然后询问HWC
计划如何处理HWC
会将这些layer
标记为client合成
或者device合成
并告知SurfaceFlinger
SurfaceFlinger
将处理标记为client合成
的layer
,然后通过BufferQueue
传递给HWC
- 余下的
layer
由HWC
自行处理
- 官网关于
网上一篇很有趣的渲染总结(文中有些错误,但瑕不掩瑜):Android渲染原理
VSYNC信号
前面提到Linux
使用Framebuffer
来用作显示输出。但是,如果在屏幕更新到一半时,用户进程更新了Framebuffer
中的数据,将导致屏幕上画面的上半部分是前一帧的画面,下半部分变成了新的画面。当然这种异常会在下次刷新时纠正过来,但是在用户感知上画面会出现闪烁感
- 针对这种情况,早期的解决方法是使用
双缓冲机制
,双缓冲就是提供两块Framebuffer
,一块用于显示,另一块用于数据更新,数据准备好后,通过ioctl
操作告诉显示设备切换用于显示的Framebuffer
,这样图像就能快速的显示出来了 - 但是双缓冲并没有完全解决问题,虽然双缓冲切换的速度很快,但是如果切换的时间点不对,在画面更新一半的时候进行切换,还是会出现单缓冲区遇到的闪烁问题
- 当然,可以在底层进行控制,当收到切换请求后内部并不马上执行,而是等到刷新完成后再切换,这样可以完全避免画面重叠的问题
- 但是,这样做会带来新的问题,如果
ioctl
操作完成后缓冲区没有切换,应用就不能确定何时可以再使用缓存区,只能通过ioctl
不停地查询缓冲区状态,直到切换完成。这种CPU
主动查询的方式很低效
为此Android
让底层固定地发送信号给用户进程,通知进程切换的时机,这样就避免了用户进程主动查询的操作。而这个信号就是VSYNC
信号
官方传送门:
VSYNC
官方描述如下:VSYNC
信号用来同步整个显示流程(Display Pipeline)
。显示流程
包括app
渲染、SurfaceFlinger
合成、HWC
(硬件渲染)组成
(这部分感觉原文更容易理解)VSYNC synchronizes the time apps wake up to start rendering, the time SurfaceFlinger wakes up to composite the screen, and the display refresh cycle.
VSYNC
信号应该由显示驱动产生,这样才能达到最佳效果。但是Android
为了能运行在不支持VSYNC
机制的设备上,也提供了用软件来模拟产生VSYNC
信号的手段
官网描述:通过
HWC
来产生VSYNC
信号,并通过接口回调将事件进行发送(主要是SurfaceFlinger
进行事件接收)
基础知识铺垫完成,我们先来看看Surface
Surface
官网对
Surface
的描述是:A surface is an interface for a producer to exchange buffers with a consumer.
上面描述的是一种生产者-消费者
的模式,而Surface
充当了中间衔接的角色。
以Activity
中UI
显示为例:
-
生产者
的任务就是把图形绘制在Surface
对象上- 比较出名的生产者就是
SurfaceView
组件了
- 比较出名的生产者就是
-
SurfaceFlinger
作为消费者
会把所有Surface
对应的图像层混合在一起 -
最后
消费者
将其输出到FrameBuffer
中,这样在屏幕上就看到最后合成的图像了
下面我们从Java层
开始分析Surface
应用中Surface
的创建过程
应用开发中很少直接使用Surface
,因为每个Activity
中都已经创建好了各自的Surface
对象,通常只有一些特殊的应用才需要在Activity
之外再去创建Surface
,例如相机、视频播放应用。
不过,通常这些应用也是通过创建SurfaceView
来使用Surface
需要注意的是,在应用中不能直接去创建一个可用的Surface
对象(也可以说直接创建出的对象没什么实际用途),因为这样创建出的Surface
对象和SurfaceFlinger
之间没有任何关联。
该如何创见一个可用的Surface
对象呢?
我们看下Surface
类的定义:
public class Surface implements Parcelable {
long mNativeObject;
// 一个无参构造,空实现
public Surface() {
}
public Surface(SurfaceTexture surfaceTexture) {
if (surfaceTexture == null) {
throw new IllegalArgumentException("surfaceTexture must not be null");
}
mIsSingleBuffered = surfaceTexture.isSingleBuffered();
synchronized (mLock) {
mName = surfaceTexture.toString();
setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
}
}
}
Surface
类对外有两个构造方法:
-
一个是无参构造,实现也是空的
- 注释中说这个主要是给
readFromParcel()
反序列化用的 - 那我们看下
readFromParcel()
方法
public void readFromParcel(Parcel source) { if (source == null) { throw new IllegalArgumentException("source must not be null"); } synchronized (mLock) { mName = source.readString(); mIsSingleBuffered = source.readInt() != 0; setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source)); } }
- 注释中说这个主要是给
-
另一个需要传递
SurfaceTexture
对象作为参数- 这就复杂了,还要准备一个
SurfaceTexture
对象
- 这就复杂了,还要准备一个
聪明的我们会发现,readFromParcel()
和new Surface(SurfaceTexture surfaceTexture)
都会执行一个setNativeObjectLocked()
方法,我们看下方法实现:
private void setNativeObjectLocked(long ptr) {
if (mNativeObject != ptr) {
...
mNativeObject = ptr;
...
}
}
setNativeObjectLocked()
方法很简单,只是更新了mNativeObject
变量的数值,重点就是参数了:
setNativeObjectLocked(nativeReadFromParcel(mNativeObject, source));
setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
这两个setNativeObjectLocked()
方法的调用从参数的命名来看是针对不同数据来源的处理。
看来要看下native
的实现了,以nativeReadFromParcel()
为例来看下:
static jlong nativeReadFromParcel(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject parcelObj) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);
...
android::view::Surface surfaceShim;
// 解析 Parcel 数据,并填充到 native层 的 Surface对象 surfaceShim
surfaceShim.readFromParcel(parcel, /*nameAlreadyRead*/true);
// 将传入的指针转换为 native层 的 Surface对象 self
sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
// 比对 surfaceShim 和 self 中的 Binder 对象 IGraphicBufferProducer
if (self != nullptr
&& (IInterface::asBinder(self->getIGraphicBufferProducer()) ==
IInterface::asBinder(surfaceShim.graphicBufferProducer))) {
// 判断是同一个 IGraphicBufferProducer ,直接返回当前指针
return jlong(self.get());
}
sp<Surface> sur;
if (surfaceShim.graphicBufferProducer != nullptr) {
// IGraphicBufferProducer 不同
// 且 surfaceShim 的 IGraphicBufferProducer 不为空
// 创建一个新的 Surface 对象 sur
sur = new Surface(surfaceShim.graphicBufferProducer, true);
sur->incStrong(&sRefBaseOwner);
}
...
// 将 sur 的指针返回给 Java 层
return jlong(sur.get());
}
到这里我们不难看出
Java层
的Surface
对象最重要的数据是mNativeObject
变量mNativeObject
是一个指针,指向的native
层的Surface
对象
native
层在判断是否新建Surface
对象的逻辑依赖的是IGraphicBufferProducer
对象IGraphicBufferProducer
对象是一个Binder
引用对象
那么接下来我们重点就是这个IGraphicBufferProducer
了。
我们先看下native层
中Surface
类的继承关系:
class Surface
: public ANativeObjectBase<ANativeWindow, Surface, RefBase>
ANativeObjectBase
的定义如下:
template <typename NATIVE_TYPE, typename TYPE, typename REF,
typename NATIVE_BASE = android_native_base_t>
class ANativeObjectBase : public NATIVE_TYPE, public REF
{...}
整理成继承关系图就是:
再看下Surface
的构造方法:
Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp)
: mGraphicBufferProducer(bufferProducer),
mCrop(Rect::EMPTY_RECT),
mBufferAge(0),
...
mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>()) {
... // 初始化各种成员变量
}
从构造函数的参数可以看到,native层
的Surface
将IGraphicBufferProducer
对象保存到了mGraphicBufferProducer
变量中。
暂时还是不清楚mGraphicBufferProducer
哪里来的,我们去WMS
中看看
WMS
中Surface
的创建过程
此处要从Activity
的onResume()
生命周期说起
onResume()
到WMS.relayoutWindow()
我们已经知道,当AMS
触发onResume()
生命周期时会调用到ActivityThread
类的handleResumeActivity()
方法,代码如下:
public void handleResumeActivity(...) {
...
// 此处会触发 onResume 声明周期回调
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
...
ViewManager wm = a.getWindowManager();
...// 省略很多 Window 处理逻辑
wm.addView(decor, l);
...
}
从方法中可以看到,执行完onResume()
后调用了ViewManager
的addView(decor, l)
方法
知识点:在
onResume
方法调用后才真正进行View
的添加
ViewManager
是一个接口类,真正的实现类是WindowManagerImpl
,addView()
方法实现也很简单:
public void addView(...) {
applyDefaultToken(params);
mGlobal.addView(...);
}
调用了mGlobal
的addView()
方法方法,mGlobal
的类型是WindowManagerGlobal
,代码如下:
public void addView(...) {
...
ViewRootImpl root;
synchronized (mLock) {
...
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
try {
root.setView(view, wparams, panelParentView);
}
...
}
}
WindowManagerGlobal
类的addView()
先是创建了一个新的ViewRootImpl
对象,然后调用了ViewRootImpl
对象的setView()
方法。
ViewRootImpl
类中setView()
调用流程如下:
class ViewRootImpl{
/**
* 这里也是直接 new 出来的对象 Surface
* 前面已经介绍过,这个对象需要和 native层进行绑定后才能正常使用
*/
public final Surface mSurface = new Surface();
ViewRootImpl(Context context, Display display){
...
// 此方法会创建 Session 对象
mWindowSession = WindowManagerGlobal.getWindowSession();
...
}
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
if (mView == null) {
mView = view;
...
// 内部方法调用
requestLayout();
...
// 此方法会创建 SurfaceSession
res = mWindowSession.addToDisplay(...);
...
}
}
}
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
...
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
...
// 异步执行 mTraversalRunnable
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
...
}
}
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
void doTraversal() {
if (mTraversalScheduled) {
...
performTraversals();
...
}
}
private void performTraversals() {
...
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
...
}
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
...
// 调用 mWindowSession 的 relayout 方法,并将 mSurface 对象传递过去
int relayoutResult = mWindowSession.relayout(..., mSurface);
...
return relayoutResult;
}
}
setView()
方法最后调用的是mWindowSession
的relayout()
方法。
mWindowSession
类型是IWindowSession
,是一个Binder
引用对象。真正的Binder
服务实现是com.android.server.wm.Session
类:
class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
public Session(WindowManagerService service, ...) {
mService = service;
...
}
public int relayout(..., Surface outSurface) {
...
int res = mService.relayoutWindow(..., outSurface);
...
return res;
}
}
终于走到了WMS
中,调用的是WMS
的relayoutWindow()
方法
WMS.relayoutWindow()
到SurfaceControl.nativeCreate()
和Surface
相关的调用关系如下:
class WindowManagerService{
public int relayoutWindow(..., Surface outSurface) {
...
result = createSurfaceControl(outSurface, ...);
...
return result;
}
private int createSurfaceControl(Surface outSurface, ...) {
...
WindowSurfaceController surfaceController;
...
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
...
if (surfaceController != null) {
surfaceController.getSurface(outSurface);
} else {
...
outSurface.release();
}
return result;
}
}
class WindowSurfaceController{
public WindowSurfaceController(...) {
...
final SurfaceControl.Builder b = win.makeSurface()
...
.setMetadata(windowType, ownerUid);
mSurfaceControl = b.build();
}
void getSurface(Surface outSurface) {
outSurface.copyFrom(mSurfaceControl);
}
}
class Surface{
public void copyFrom(SurfaceControl other) {
if (other == null) {
throw new IllegalArgumentException("other must not be null");
}
long surfaceControlPtr = other.mNativeObject;
if (surfaceControlPtr == 0) {
throw new NullPointerException(
"null SurfaceControl native object. Are you using a released SurfaceControl?");
}
long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr);
synchronized (mLock) {
if (mNativeObject != 0) {
nativeRelease(mNativeObject);
}
setNativeObjectLocked(newNativeObject);
}
}
}
在上面的relayoutWindow()
方法中
WMS
先通过winAnimator
的createSurfaceLocked()
方法得到了一个WindowSurfaceController
对象WindowSurfaceController
对象封装了SurfaceControl
对象
- 然后
WMS
调用WindowSurfaceController
对象的getSurface()
方法来对Surface
对象进行填充getSurface()
对象只是利用自身保存的mSurfaceControl
对象- 通过
Surface
的copyFrom()
方法对Surface
对象进行填充处理
copyFrom()
方法- 调用
nativeGetFromSurfaceControl()
方法得到一个native
层的Surface
对象指针 - 然后通过
setNativeObjectLocked()
方法将指针保存到成员变量mNativeObject
中
- 调用
关键点又回到了native
层的nativeGetFromSurfaceControl()
方法,它的代码如下:
static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz,
jlong surfaceControlNativeObj) {
sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
sp<Surface> surface(ctrl->getSurface());
if (surface != NULL) {
surface->incStrong(&sRefBaseOwner);
}
return reinterpret_cast<jlong>(surface.get());
}
nativeGetFromSurfaceControl()
方法是通过native
层的SurfaceControl
的getSurface()
方法来获取Surface
对象。我们再看下getSurface()
方法:
sp<Surface> SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
return generateSurfaceLocked();
}
return mSurfaceData;
}
sp<Surface> SurfaceControl::generateSurfaceLocked() const
{
mSurfaceData = new Surface(mGraphicBufferProducer, false);
return mSurfaceData;
}
在SurfaceControl
的getSurface()
方法中
- 当
mSurfaceData
指针为空时才会通过generateSurfaceLocked()
方法创建一个新的Surface
对象Surface
对象中很关键的IGraphicBufferProducer
在这里传入的是SurfaceControl
的成员变量mGraphicBufferProducer
- 否则直接返回
mSurfaceData
指针
从getSurface()
方法的逻辑中我们不难看出,SurfaceControl
对象和Surface
对象是关联在一起的,一对一的关系
更关键的是构造Surface
对象的核心参数竟然是SurfaceControl
中的成员变量。。。。。。。。
没办法,要先搞定SurfaceControl
的创建过程才可以
前面已经讲过,WMS
通过winAnimator.createSurfaceLocked()
方法创建了WindowSurfaceController
对象,WindowSurfaceController
对象初始化时就会创建SurfaceControl
,我们看下创建过程:
class WindowStateAnimator{
WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {
...
// mSession 的类型就是前面提到的 Session 类,IWindowSession Binder服务类
mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession, ...);
...
return mSurfaceController;
}
}
class WindowSurfaceController{
public WindowSurfaceController(SurfaceSession s, ...) {
...
final SurfaceControl.Builder b = win.makeSurface()
...
.setMetadata(windowType, ownerUid);
// 通过 Builder 模式创建的
mSurfaceControl = b.build();
}
}
class SurfaceControl{
public static class Builder {
...
public SurfaceControl build() {
...
// 调用私有构造方法
return new SurfaceControl(mSession, ...);
}
...
}
private SurfaceControl(SurfaceSession session, ...)
throws OutOfResourcesException, IllegalArgumentException {
...
mNativeObject = nativeCreate(session, ...);
if (mNativeObject == 0) {
throw new OutOfResourcesException(
"Couldn't allocate SurfaceControl native object");
}
...
}
}
可以看到
- 创建
SurfaceControl
对象的全程都携带着一个SurfaceSession
对象。 - 同时这个
SurfaceSession
对象在SurfaceControl
的构造方法中通过nativeCreate()
传递到了native层
,用来创建native层
的对象 - 和
Java层
的Surface
对象一样,SurfaceControl
对象也会将native层
对象的指针保存到mNativeObject
中
关键还是在nativeCreate()
方法,我们继续。。
nativeCreate()
方法如下:
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, ...) {
ScopedUtfChars name(env, nameStr);
sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
...
sp<SurfaceControl> surface;
status_t err = client->createSurfaceChecked(
String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
...
return reinterpret_cast<jlong>(surface.get());
}
nativeCreate()
方法中又出现了一个新的类型SurfaceComposerClient
,而且native层
的SurfaceControl
对象就是通过它的createSurfaceChecked()
来创建的
耐心、耐心、耐心。。。。 崩溃的时候多说几次
上面方法中的SurfaceComposerClient
对象是通过android_view_SurfaceSession_getClient()
方法得到的,看JNI
的命名格式可以推算它和SurfaceSession
类也有关系,内容如下:
sp<SurfaceComposerClient> android_view_SurfaceSession_getClient(
JNIEnv* env, jobject surfaceSessionObj) {
return reinterpret_cast<SurfaceComposerClient*>(
env->GetLongField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
}
android_view_SurfaceSession_getClient()
方法中的参数surfaceSessionObj
是在Java层
调用nativeCreate()
方法时传递的参数,类型是SurfaceSession
。
这里实际上是将
SurfaceSession
对象中成员变量mNativeClient
的值取出来后,转换为SurfaceComposerClient
对象返回
这说明SurfaceComposerClient
对象和SurfaceSession
对象也是一起创建出来的,我们继续看下SurfaceSession
和SurfaceComposerClient
的创建过程
SurfaceControl.nativeCreate
到ComposerService
需要知道的一个重要前提:每个用户进程在
WMS
中都有且只有一个对应的Session
对象,前面已经介绍Session
是一个实现了IWindowSession
接口的Binder
服务类
Session
的成员变量mSurfaceSession
是在Session
对象初始化时创建的,那么Session
对象在什么时候创建的呢?
跟踪代码发现流程如下:
ViewRootImpl
初始化时会调用WindowManagerGlobal.getWindowSession()
方法WindowManagerGlobal.getWindowSession()
会调用WMS
的openSession()
方法openSession()
方法中便会在WMS
中创建一个新的Session
对象
对于SurfaceSession
的初始化,是在Session
对象的windowAddedLocked()
方法中,那么windowAddedLocked()
方法又是在哪里调用的呢?
同样,我们跟踪下方法调用:
ViewRootImpl
的setView()
方法中会调用mWindowSession.addToDisplay(...)
方法mWindowSession.addToDisplay(...)
方法会调用WMS
的addWindow()
方法WMS
的addWindow()
方法会调用WindowState
的attach()
方法attach()
方法会调用Session
的windowAddedLocked()
方法
这样就串起来了,现在我们可以继续学习SurfaceSession
的构造方法了:
/** Create a new connection with the surface flinger. */
public SurfaceSession() {
mNativeClient = nativeCreate();
}
很简洁,源码注释也很关键。我们看下SurfaceSession
的nativeCreate()
方法:
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient();
// 请注意此方法的调用
// 该方法会触发 onFirstRef() 的执行
client->incStrong((void*)nativeCreate);
return reinterpret_cast<jlong>(client);
}
nativeCreate()
直接创建了一个SurfaceComposerClient
对象,也没有参数。不过SurfaceComposerClient
类是从RefBase
类派生出来的,我们看下它的构造函数和onFirstRef
函数:
SurfaceComposerClient::SurfaceComposerClient()
: mStatus(NO_INIT)
{
}
// onFirstRef() 是 RefBase 提供的回调接口
// 当首次调用 incStrong() 方法时便会执行此方法
void SurfaceComposerClient::onFirstRef() {
sp<ISurfaceComposer> sf(ComposerService::getComposerService());
if (sf != 0 && mStatus == NO_INIT) {
// 此处 rootProducer 应该为 null
auto rootProducer = mParent.promote();
sp<ISurfaceComposerClient> conn;
// 所以在此处执行的是 sf->createConnection() 方法
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
if (conn != 0) {
mClient = conn;
mStatus = NO_ERROR;
}
}
}
构造方法很简单,只是将mStatus
设置为NO_INIT
。
重点是在onFirstRef()
方法中
- 先调用了
ComposerService
的getComposerService()
方法来得到一个ISurfaceComposer
的指针 - 然后调用它的
createConnection()
方法创建一个ISurfaceComposerClient
对象 - 然后将
mClient
指向这个ISurfaceComposerClient
对象
咳咳咳,按照上面的调用流程我们还没有找到关于
IGraphicBufferProducer
的信息,现在又多出来了一个ISurfaceComposerClient
。。。
好吧好吧,梳理下这部分关系先
WMS
中Surface
关系总结
上面介绍的WMS
中涉及和Surface
有关的类关系如下:
看上去就挺复杂的:
SurfaceControl
和Surface
是成对创建的,考虑到绘制等需求,它们的数量会比较多Session
、SurfaceSession
和SurfaceComposerClient
对象是和连接WMS
的用户进程的数量相同SurfaceComposerClient
的作用是创建Surface
SurfaceControl
通过SurfaceComposerClient
来获取Surface
SurfaceComposerClient
是ComposerService
的具体实现类
ComposerService
再到SurfaceFlinger
ComposerService
是一个单例模式的普通类,定义如下:
class ComposerService : public Singleton<ComposerService>
{
sp<ISurfaceComposer> mComposerService;
sp<IBinder::DeathRecipient> mDeathObserver;
Mutex mLock;
ComposerService();
void connectLocked();
void composerServiceDied();
friend class Singleton<ComposerService>;
public:
static sp<ISurfaceComposer> getComposerService();
};
前面的onFirstRef()
方法中调用了ComposerService
类的静态方法getComposerService()
,我们看下它的实现:
/*static*/ sp<ISurfaceComposer> ComposerService::getComposerService() {
ComposerService& instance = ComposerService::getInstance();
Mutex::Autolock _l(instance.mLock);
if (instance.mComposerService == NULL) {
ComposerService::getInstance().connectLocked();
...
}
return instance.mComposerService;
}
getComposerService()
通过调用父类Singleton
的getInstance()
方法来取得实例对象,然后调用ComposerService
的connectLocked()
方法:
void ComposerService::connectLocked() {
const String16 name("SurfaceFlinger");
while (getService(name, &mComposerService) != NO_ERROR) {
usleep(250000);
}
...
}
connectLocked()
方法中连接了SurfaceFlinger
服务对象,然后把对象指针保存到mComposerService
中。
ComposerService
其实只是SurfaceFlinger
的代理,它把SurfaceFlinger
服务接口包装了起来
getComposerService()
返回的就是mComposerService
对象指针,也就是SurfaceFlinger
的Binder
对象。
前面提到,SurfaceComposerClient
对象的onFirstRef()
方法中
- 在通过
ComposerService::getComposerService()
获得了mComposerService
指针后 - 调用了
mComposerService
对象的createConnection()
方法。 - 按照刚才的逻辑,其实调用是
SurfaceFlinger
服务的相关函数接口。
SurfaceFlinger
中接口实现如下:
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
return initClient(new Client(this));
}
static sp<ISurfaceComposerClient> initClient(const sp<Client>& client) {
status_t err = client->initCheck();
if (err == NO_ERROR) {
return client;
}
return nullptr;
}
createConnection()
函数中创建了一个Client
类型对象,然后将其返回给调用者,关于Client
类的定义如下:
class Client : public BnSurfaceComposerClient
Client
是一个Binder
服务类,虽然叫Client
。而mComposerService
保存的也就是这个服务对象的指针
我们再回到SurfaceControl
的创建过程
nativeCreate()
方法中调用了SurfaceComposerClient
的createSurfaceChecked()
方法
status_t SurfaceComposerClient::createSurfaceChecked(...)
{
sp<SurfaceControl> sur;
status_t err = mStatus;
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IBinder> parentHandle;
sp<IGraphicBufferProducer> gbp;
if (parent != nullptr) {
parentHandle = parent->getHandle();
}
err = mClient->createSurface(name, w, h, format, flags, parentHandle,
windowType, ownerUid, &handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
*outSurface = new SurfaceControl(this, handle, gbp, true /* owned */);
}
}
return err;
}
createSurfaceChecked()
方法
- 先是调用了
SurfaceFlinger::Client
对象的createSurface()
方法去进行创建操作- 请留意传递的参数,
handle
、gbp
、parentHandle
都是Binder
对象sp<IGraphicBufferProducer> gbp
就是我们找寻已久的参数。。。。- 这些参数都会在
SurfaceFlinger
中进行设置
- 请留意传递的参数,
- 最后确认
SurfaceFlinger::Client
对象的createSurface()
执行完成没有错误,创建SurfaceControl
对象
SurfaceFlinger
中创建Surface
SurfaceFlinger::Client
对象的createSurface()
方法如下:
status_t Client::createSurface(...,
sp<IGraphicBufferProducer>* gbp)
{
...
return mFlinger->createLayer(..., gbp, &parent);
}
调用的是SurfaceFlinger
的createLayer()
方法,代码如下:
status_t SurfaceFlinger::createLayer(...,
sp<IGraphicBufferProducer>* gbp, sp<Layer>* parent)
{
...
status_t result = NO_ERROR;
sp<Layer> layer;
String8 uniqueName = getUniqueLayerName(name);
// 这里分成了两种创建模式:Normal 和 Color
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal: // normal
result = createBufferLayer(client,
uniqueName, w, h, flags, format,
handle, gbp, &layer);
break;
case ISurfaceComposerClient::eFXSurfaceColor: // color
result = createColorLayer(client,
uniqueName, w, h, flags,
handle, &layer);
break;
default:
result = BAD_VALUE;
break;
}
...
return result;
}
createLayer()
方法按照两种模式进行创建
-
一种是
eFXSurfaceNormal
模式,通过createBufferLayer()
方法创建,方法如下:status_t SurfaceFlinger::createBufferLayer(..., sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer) { // initialize the surfaces switch (format) { case PIXEL_FORMAT_TRANSPARENT: case PIXEL_FORMAT_TRANSLUCENT: // 透明或半透明设置格式为 RGBA format = PIXEL_FORMAT_RGBA_8888; break; case PIXEL_FORMAT_OPAQUE: // 不透明设置格式为 RGBX format = PIXEL_FORMAT_RGBX_8888; break; } sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags); status_t err = layer->setBuffers(w, h, format, flags); if (err == NO_ERROR) { *handle = layer->getHandle(); // 我们关注的 IGraphicBufferProducer 在这里赋值了 *gbp = layer->getProducer(); *outLayer = layer; } return err; }
- 方法中先是确定相应的像素格式,然后创建新的
BufferLayer
对象,调用对象的setBuffers()
设置宽高和像素格式 Surface
中重要的gdp
等参数也会在这里进行设置
- 方法中先是确定相应的像素格式,然后创建新的
-
一种是
eFXSurfaceColor
模式,通过createColorLayer()
方法创建:看参数传入和gdp
没啥关系,不用太过关注status_t SurfaceFlinger::createColorLayer(..., sp<IBinder>* handle, sp<Layer>* outLayer) { *outLayer = new ColorLayer(this, client, name, w, h, flags); *handle = (*outLayer)->getHandle(); return NO_ERROR; }
- 方法比较简单只是创建了一个
ColorLayer
对象,也没有setBuffers()
等操作
- 方法比较简单只是创建了一个
我们重点关注eFXSurfaceNormal
模式的创建逻辑
终于,我们找到了
sp<IGraphicBufferProducer>* gbp
的来源,是通过layer->getProducer()
方法
layer->getProducer()
方法如下:
sp<IGraphicBufferProducer> BufferLayer::getProducer() const {
return mProducer;
}
layer->getProducer()
方法比较简单,只是返回了一个mProducer
对象的指针
mProducer
对象的创建是在BufferLayer::onFirstRef()
方法中
void BufferLayer::onFirstRef() {
Layer::onFirstRef();
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
// 通过 BufferQueue 的 createBufferQueue 方法创建 producer 和 consumer
BufferQueue::createBufferQueue(&producer, &consumer, true);
// 创建 mProducer
mProducer = new MonitoredProducer(producer, mFlinger, this);
...
}
onFirstRef()
方法中
- 通过
BufferQueue::createBufferQueue()
方法创建producer
和consumer
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer, sp<IGraphicBufferConsumer>* outConsumer, bool consumerIsSurfaceFlinger) { sp<BufferQueueCore> core(new BufferQueueCore()); sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger)); sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core)); *outProducer = producer; *outConsumer = consumer; }
- 利用创建好的
producer
对象创建MonitoredProducer
对象
MonitoredProducer
头文件定义如下:
class MonitoredProducer : public BnGraphicBufferProducer {
public:
MonitoredProducer(const sp<IGraphicBufferProducer>& producer,
const sp<SurfaceFlinger>& flinger,
const wp<Layer>& layer);
virtual ~MonitoredProducer();
...
private:
// 在 BufferLayer 的 onFirstRef() 中通过 BufferQueue::createBufferQueue() 创建
sp<IGraphicBufferProducer> mProducer;
sp<SurfaceFlinger> mFlinger;
wp<Layer> mLayer;
}
虽然MonitoredProducer
是一个Binder
实体对象,但从业务上来讲它仅仅是个代理
真正管理图像缓冲区的是通过
BufferQueue::createBufferQueue()
方法创建的BufferQueueProducer producer
对象
终于接近IGraphicBufferProducer
的本质了,到这里我们其实可以结束WMS
中Surface
的创建流程了。先回顾下整个创建流程:
上图分了三部分
- 绿色部分:
Surface
和Session
的初始化 - 蓝色部分:
ViewRootImpl
的setView()
中执行performTraversals()
- 这部分主要是创建
SurfaceControl
对象 - 然后对
Surface
对象进行填充 - 从
scheduleTraversals()
调用流程来看,这是一个异步过程
- 这部分主要是创建
- 青色部分:
ViewRootImpl
的setView()
中执行session.addToDisplay()
- 这部分主要是创建
SurfaceSession
对象 - 在
native
层创建SurfaceComposerClient
对象
- 这部分主要是创建
需要注意的一点是SurfaceControl
对象的创建需要SurfaceSession
对象作为参数。但setView()
方法中SurfaceSession
对象的创建放在了SurfaceControl
对象的后面
一开始其实挺疑惑的,核心还是在scheduleTraversals()
的异步调用过程,感兴趣的同学可以参考:scheduleTraversals
到底做了什么
管理图像缓冲区IGraphicBufferProducer
我们一直强调Surface
中最重要的对象是IGraphicBufferProducer
,最后我们也找到了它对应的Binder
实体对象MonitoredProducer
对象
- 对于
MonitoredProducer
对象来说,它又关联了一个sp<IGraphicBufferProducer>
对象mProducer
mProducer
对象具体的实现类是BufferQueueProducer
前面说Surface
像一张画布,那么Surface
为什么要和BufferQueue
关联呢?
- 对于图像显示设备而言,它的刷新周期是固定的,必须在它需要图像的时候把数据准备好
- 播放动画时,每秒要播放至少
24帧
画面才能形成比较真实的动画效果- 而这些图像数据都是
CPU
解码得到的,准备它们需要时间
- 而这些图像数据都是
- 播放视频时的每一帧也需要在指定时间播放
- 因此解码器会提前准备好一批数据,这些数据保存在解码器内部的缓冲区中
- 当时间到达时,解码器会把内部缓冲区的图像数据复制到
Surface
中 - 但是显示设备并不能立刻把数据取走,因此
Surface
需要缓冲区来临时保存数据
BufferQueue
操作官方图解如下:
从前面的BufferQueue::createBufferQueue()
中可以看出:
MonitoredProducer
对象也只是一个代理,真正的业务处理对象是在createBufferQueue()
方法中创建的BufferQueueProducer
对象- 除此之外方法中还涉及了
BufferQueueCore
和BufferQueueConsumer
对象的创建
BufferQueue
-Core|Producer|Consumer
前面已经介绍,在BufferLayer
的onFirstRef()
方法中通过BufferQueue::createBufferQueue()
方法创建了三个对象:BufferQueueCore
、BufferQueueConsumer
和BufferQueueProducer
其中
BufferQueueCore
是核心,把BufferQueueConsumer
和BufferQueueProducer
对象连接在了一起
关于BufferQueue
的工作方式,官网有个比较直观的叙述,翻译如下:
Consumer
创建并拥有BufferQueue
数据结构,并且可存在于与其Producer
不同的进程中- 当
Producer
需要缓冲区时,它会通过调用dequeueBuffer()
从BufferQueue
请求一个可用的缓冲区,并指定缓冲区的宽度、高度、像素格式和用法标志。 - 然后,
Producer
填充缓冲区并通过调用queueBuffer()
将缓冲区返回到队列 - 接下来,
Consumer
通过acquireBuffer()
获取该缓冲区并使用该缓冲区的内容 - 当
Consumer
操作完成后,它会通过调用releaseBuffer()
将该缓冲区返回到队列
流程较为清晰,我们从源码层面再看下,首先是BufferQueueCore
中的关键定义:
class BufferQueueCore : public virtual RefBase {
friend class BufferQueueProducer;
friend class BufferQueueConsumer;
...
private:
BufferQueueDefs::SlotsType mSlots;
}
C++
中的friend
在这里用来使Producer
和Consumer
可以访问Core
中的成员变量。mSlots
是一个64
长度的BufferSlot
数组,稍后细讲
再看下BufferQueueProducer
类的定义:
class BufferQueueProducer : public BnGraphicBufferProducer,
private IBinder::DeathRecipient {
...
private:
sp<BufferQueueCore> mCore;
}
再看看BufferQueueConsumer
类的定义:
class BufferQueueConsumer : public BnGraphicBufferConsumer {
...
private:
sp<BufferQueueCore> mCore;
}
不难看出,Producer
对象和Consumer
对象通过mCore
对象连接在一起,查看Producer
和Consumer
这两个对象的具体方法我们就会发现,很多操作都是直接通过mCore
对象的函数来实现的。
Consumer
和Producer
的接口定义
继续看下BufferQueueConsumer
和BufferQueueProducer
的基类,分别是BnGraphicBufferProducer
和BnGraphicBufferConsumer
,定义如下:
class BnGraphicBufferProducer : public BnInterface<IGraphicBufferProducer>
class BnGraphicBufferConsumer : public SafeBnInterface<IGraphicBufferConsumer>
它们主要是实现了两套IGraphicBufferProducer
和IGraphicBufferConsumer
的Binder
接口,主要都是操作BufferQueue
的相关接口,定义如下:
IGraphicBufferProducer
class IGraphicBufferProducer : public IInterface { public: ... virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h, PixelFormat format, uint64_t usage, uint64_t* outBufferAge, FrameEventHistoryDelta* outTimestamps) = 0; ... virtual status_t queueBuffer(int slot, const QueueBufferInput& input, QueueBufferOutput* output) = 0; ... virtual status_t connect(const sp<IProducerListener>& listener, int api, bool producerControlledByApp, QueueBufferOutput* output) = 0; virtual status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api) = 0; ... };
BufferQueueProducer
类是IGraphicBufferProducer
的实现- 使用
Producer
相关功能时需要先通过connect()
方法建立连接 Producer
使用完毕后需要调用disconnect()
断开连接
IGraphicBufferConsumer
class IGraphicBufferConsumer : public IInterface { public: ... virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen, uint64_t maxFrameNumber = 0) = 0; virtual status_t detachBuffer(int slot) = 0; virtual status_t attachBuffer(int* outSlot, const sp<GraphicBuffer>& buffer) = 0; virtual status_t releaseBuffer(int buf, uint64_t frameNumber, EGLDisplay display, EGLSyncKHR fence, const sp<Fence>& releaseFence) = 0; virtual status_t consumerConnect(const sp<IConsumerListener>& consumer, bool controlledByApp) = 0; virtual status_t consumerDisconnect() = 0; ... };
BufferQueueConsumer
是接口IGraphicBufferConsumer
的实现- 使用
Consumer
相关功能时,需通过consumerConnect()
方法建立连接- 这里需传入
IConsumerListener
对象,这是一个回调接口 - 当数据准备好了就会调用这个对象的
onFrameAvailable()
函数来通知Consumer
来取数据
- 这里需传入
- 取数据需要调用函数
acquireBuffer()
- 使用完数据后,需调用
releaseBuffer()
来把缓冲区归还给BufferQueueCore
BufferQueue
的状态转换
前面提到BufferQueueCore
类中定义了一个64项
的数组mSlots
:
static constexpr int NUM_BUFFER_SLOTS = 64;
namespace BufferQueueDefs {
typedef BufferSlot SlotsType[NUM_BUFFER_SLOTS];
}
BufferQueueDefs::SlotsType mSlots;
mSlots
数组元素类型是BufferSlot
,关键定义如下:
struct BufferSlot {
...
sp<GraphicBuffer> mGraphicBuffer;
...
BufferState mBufferState;
...
};
mGraphicBuffer
指向图像缓冲区GraphicBuffer
的指针GraphicBuffer
对应的便是真正的图像缓存数据
mBufferState
表示图像缓冲区的状态
BufferState
定义如下:
struct BufferState {
uint32_t mDequeueCount;
uint32_t mQueueCount;
uint32_t mAcquireCount;
bool mShared;
}
BufferState
中4个变量对应的状态如下:
状态\变量 | mShared | mDequeueCount | mQueueCount | mAcquireCount |
---|---|---|---|---|
FREE | false | 0 | 0 | 0 |
DEQUEUED | false | 1 | 0 | 0 |
QUEUED | false | 0 | 1 | 0 |
ACQUIRED | false | 0 | 0 | 1 |
SHARED | true | any | any | any |
状态之间的转换关系如下:
结合前面提到的接口,我们看下整个状态转换过程的时序图:
到这里,我们已经大体了解了从Surface
到SurfaceFlinger
的数据通道,dequeueBuffer()
等方法的细节就不深入分析了,其中会涉及GraphicBuffer
的初始化过程,不影响我们对整体的掌握(主要是太难了。。。。。),不过以下几点需要注意:
GraphicBuffer
初始化时便会执行Gralloc
模块的allocate()
方法申请共享内存缓冲区- 并且在硬件设备支持
FrameBuffer
缓冲区的情况下,申请到的就是FrameBuffer
的缓冲区
显示原理和Surface
相关的内容到此结束了,还有很多不完善的地方,后面再来找补吧(又挖一坑)
关于Android
图形显示的学习还剩下SurfaceFlinger
和图像输出过程两部分,希望清明节前搞定,(ง •̀_•́)ง