本文是基于Google Android Repo中的较新的源码分析的。Android UI
渲染这一块变化还是比较大的,逻辑可能和网上大部分文章有一些出入。
在本文正式开始之前,我们先来了解一下与SurfaceFlinger相关的基础知识:
- 与SurfaceFlinger相关的基础知识
SurfaceFlinger
可以说是Android UI
渲染体系的核心,在Android系统启动时会启动SurfaceFlinger
服务,它的主要作用就是被Android应用程序调用,把绘制(测量,布局,绘制)后的窗口(Surface)渲染到手机屏幕上。所以整个
UI刷新过程可能像下面这张图:
当然实际上的UI渲染原理可没有像上图那样这么简单。为了接下来在源码追踪的过程中不迷路,我们带着下面几个问题来开始分析:
- WindowManagerService是如何管理Window的?
- Surface是如何创建的?
- SurfaceFlinger是如何管理多个应用的UI渲染的?
- SurfaceFlinger中UI渲染的基本单元是什么?
ok,接下来就开始Android UI显示原理之Surface的创建
的主要流程分析。由于整个体系的源码流程很复杂,因此在追踪源码时我只贴了一些整个流程分析中的主要节点,并且加了一些注释。
在上一篇文章中我们知道,ViewRootImpl
管理着整个view tree。
对于ViewRootImpl.setView()
,我们可以简单的把它当做一个UI渲染操作
的入口,因此我们就从这个方法开始看:
WindowManagerService对于Window的管理
ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
//mWindowSession是一个aidl,ViewRootImpl利用它来和WindowManagerService交互
//mWindow是一个aidl,WindowManagerService可以利用这个对象与服务端交互
//mAttachInfo可以理解为是一个data bean,可以跨进程传递
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
...
}
即ViewRootImpl.setView()
方法会向WindowManagerService
请求添加一个Window
,mWindowSession.addToDisplay()
跨进程最终调用到了WindowManagerService.addWindow()
:
WindowManagerService.java
public int addWindow(Session session, IWindow client...) {
...
//WindowState用来描述一个Window
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);
...
win.attach(); //会创建一个SurfaceSession
mWindowMap.put(client.asBinder(), win); //mWindowMap是WindowManagerService用来保存当前所有Window新的的集合
...
win.mToken.addWindow(win); //一个token下会有多个win state。 其实token与PhoneWindow是一一对应的。
...
}
WindowState
是WindowManagerService
用来描述应用程序的一个Window
的对象。上面注释我标注了win.attach()
,这个方法可以说是Window
与SurfaceFlinger
链接的起点,它最终会调用到Session.windowAddedLocked()
:
Session.java
void windowAddedLocked(String packageName) {
...
if (mSurfaceSession == null) {
...
mSurfaceSession = new SurfaceSession();
...
}
}
//SurfaceSession类的构造方法
public final class SurfaceSession {
private long mNativeClient; // SurfaceComposerClient*
public SurfaceSession() {
mNativeClient = nativeCreate();
}
这里调用了native方法nativeCreate()
,这个方法其实是返回了一个SurfaceComposerClient指针
。那这个对象是怎么创建的呢?
SurfaceComposerClient的创建
android_view_SurfaceSession.cpp
static jlong nativeCreate(JNIEnv* env, jclass clazz) {
SurfaceComposerClient* client = new SurfaceComposerClient(); //构造函数其实并没有做什么
client->incStrong((void*)nativeCreate);
return reinterpret_cast<jlong>(client);
}
即构造了一个SurfaceComposerClient
对象。并返回它的指针。这个对象一个应用程序就有一个,它是应用程序与SurfaceFlinger
沟通的桥梁,为什么这么说呢?在SurfaceComposerClient指针
第一次使用时会调用下面这个方法:
//这个方法在第一次使用SurfaceCo