从源码角度看WMS

简介

因为我以前接触APP层的视图绘制相关业务比较多,对View的显示相关源码相对来说更感兴趣,所以想写WMS相关的源码解析很久了,但是一直迟迟没有开始写。主要是因为WMS的确是属于Android系统中最复杂的组件之一,知识点涉及从Activity生命周期、Binder、JNI、Native再到SurfaceFlinger等方方面面,分析起来容易陷入无形的大网中迷失方向

之前我有分析过View视图的测量、布局、绘制与Activity的联系,也分析过ViewRootImpl在App客户端的地位,其实就是为了这篇做准备,现在感觉基础的知识点已经具备了。但是一篇博客的内容实在是太难覆盖WMS相关的知识点了, 所以我对其中的代码进行了一定的删减,避免陷入阅读源码细节的囧境

我的目的本身是为了理解WMS在视图绘制的角色,本文中尽量多画图,少列举代码,方便快速的理解App, WMS与SurfaceFlinger的交互模式与流程

设计图

架构图

视图绘制流程:

  1. AMS binder call到应用,Activity到resume的生命周期
  2. Activity调用WMSGlobal,委托ViewRootImpl进行addWindow操作
  3. ViewRootImpl binder call到system_server到Session服务
  4. Session将请求委托给WMS,创建WindowToken, WindowState
  5. ViewRootImpl首次调用performTraverals进行窗口刷新
  6. ViewRootImpl调用到WMS,创建SurfaceControl
  7. WMS binder call到SurfaceFlinger进行Layer, producer, consumer, bufferqueue的初始化
  8. SurfaceControl返回Surface给App客户端
  9. App客户端调用View.onDraw方法进行绘制
  10. ViewRootImpl通过Surface的producer句柄binder call到SurfaceFlinger进行绘制

类图

  • ViewRootImpl: 应用进程中视图相关管理类
  • WindowManagerGlobal: 应用进程中WMS相关管理类
  • Surface: 视图的封装,本质上是和SurfaceFlinger通信的”钥匙”
  • WMS: 用于组织安卓系统中不同视图的层级、动画、大小等,并不参与绘制
  • SurfaceControl: 用于创建、获取、设置Surface
  • SurfaceFlinger: 安卓系统中真正进行绘制的进程服务
  • BufferQueueProducer: 绘制生产者
  • BufferQueueConsumer: 绘制消费者
  • BufferQueue: 绘制队列
  • Layer: 在SurfaceFlinger服务中的窗口表示类

新建窗口: WMS.addWindow

frameworks/base/core/java/android/app/ActivityThread.java

1
2
3
4
5
6
7
8
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
...
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
...
}

关于窗口的新建与添加,我直接跳过了Activity的启动流程,直接从AMS调用scheduleResumeActivity到App端后讲起,当Activity可见时,回调用对应Activity的makeVisible方法进行可视化

frameworks/base/core/java/android/app/Activity.java

1
2
3
4
5
6
7
8
9
void makeVisible() {
// 如果窗口之前并没有被添加,那么先获取WindowManager服务进行添加
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}

frameworks/base/core/java/android/view/WindowManagerGlobal.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
...
// App端视图相关的大管家是ViewRootImpl,一个窗口会对应一个,这里进行新建
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
// 保存在列表中
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// 这里进行视图设置相关操作
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
...
}
}

和ViewRootImpl的控制器角色类似,WindowManagerGlobal是窗口相关的控制器,专门用来协调窗口相关的操作

1
2
3
4
5
6
7
8
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
...
}

ViewRootImpl并没有和WindowManagerService直接进行通信,而是通过运行在system_server的WindowSession服务进行了中转

frameworks/base/services/core/java/com/android/server/wm/Session.java

1
2
3
4
5
6
7
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outContentInsets, Rect outStableInsets,
Rect outOutsets, InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId,
outContentInsets, outStableInsets, outOutsets, outInputChannel);
}

这里并没有进行多余的操作,直接中转到WMS进行处理

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public int addWindow(Session session, IWindow client, int seq,
WindowManager.LayoutParams attrs, int viewVisibility, int displayId,
Rect outContentInsets, Rect outStableInsets, Rect outOutsets,
InputChannel outInputChannel) {
...
// 尝试获取token
WindowToken token = mTokenMap.get(attrs.token);
if (token == null) {
// 如果为空,那么会新建一个WindowToken
token = new WindowToken(this, attrs.token, -1, false);
}
...
// 新创建一个WindowState
WindowState win = new WindowState(this, session, client, token,
attachedWindow, appOp[0], seq, attrs, viewVisibility, displayContent);
...
// 进行保存
mWindowMap.put(client.asBinder(), win);
...
}

至此,创建视图的大概操作已经完成,addWindow的操作主要在于初始化WindowToken, WindowState这两个数据结构,WMS正是主要凭借着它们来组织视图的系统层级结构的

刷新窗口: WMS.relayoutWindow

frameworks/base/core/java/android/view/ViewRootImpl.java

1
2
3
4
5
6
7
8
void scheduleTraversals() {
if (!mTraversalScheduled) {
...
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
...
}
}

窗口的刷新是由VSYNC进行控制的,主要是通过调用scheduleTraversals方法进行实现,这里可以看到,主要是通过mChoreographer发送了一个Message进行实现的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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 {
...
int relayoutResult = mWindowSession.relayout(
mWindow, mSeq, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f),
viewVisibility, insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,
mWinFrame, mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets,
mPendingStableInsets, mPendingOutsets, mPendingBackDropFrame, mPendingConfiguration,
mSurface);
...
}

TraversalRunnable这个类中,主要是进行doTraversal的调用,最终同样是通过mWindowSession binder call到system_server进行处理

frameworks/base/services/core/java/com/android/server/wm/Session.java

1
2
3
4
5
6
7
public int relayout(IWindow window, int seq...) {
int res = mService.relayoutWindow(this, window, seq, attrs,
requestedWidth, requestedHeight, viewFlags, flags,
outFrame, outOverscanInsets, outContentInsets, outVisibleInsets,
outStableInsets, outsets, outBackdropFrame, outConfig, outSurface);
return res;
}

Session的调用仅仅是起到了中转的作用

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public int relayoutWindow(Session session, IWindow client...) {
...
// 首先获取到对应的WindowState
WindowState win = windowForClientLocked(session, client, false);
...
WindowStateAnimator winAnimator = win.mWinAnimator;
// 随后创建Surface
result = createSurfaceControl(outSurface, result, win, winAnimator);
}
private int createSurfaceControl(Surface outSurface, int result, WindowState win, WindowStateAnimator winAnimator) {
...
// 创建Surface
WindowSurfaceController surfaceController = winAnimator.createSurfaceLocked();
if (surfaceController != null) {
// 进行拷贝
surfaceController.getSurface(outSurface);
} else {
// For some reason there isn't a surface. Clear the
// caller's object so they see the same state.
outSurface.release();
}
return result;
}

Surface的创建其实是层层委托,最终交给了SurfaceControl去创建Surface

frameworks/base/services/core/java/com/android/server/wm/WindowSurfaceController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public WindowSurfaceController(SurfaceSession s,
String name, int w, int h, int format, int flags, WindowStateAnimator animator) {
...
if (animator.mWin.isChildWindow() &&
animator.mWin.mSubLayer < 0 &&
animator.mWin.mAppToken != null) {
...
} else if (DEBUG_SURFACE_TRACE) {
...
} else {
mSurfaceControl = new SurfaceControl(
s, name, w, h, format, flags);
}
}

frameworks/base/core/java/android/view/SurfaceControl.java

1
2
3
4
5
6
7
public SurfaceControl(SurfaceSession session,
String name, int w, int h, int format, int flags)
throws OutOfResourcesException {
...
mNativeObject = nativeCreate(session, name, w, h, format, flags);
...
}

在调用nativeCreate后,Surface的创建就完成了,之后通过SurfaceControl可以将它的成员Surface进行拷贝,随后会返回给App客户端

接下来深入到native中就看看Surface的初始化

frameworks/base/core/jni/android_view_SurfaceControl.cpp

1
2
3
4
5
6
7
8
9
10
11
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
jstring nameStr, jint w, jint h, jint format, jint flags) {
ScopedUtfChars name(env, nameStr);
sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
// 发送binder call到运行在surface flinger的进程SurfaceComposerClient服务进行创建
sp<SurfaceControl> surface = client->createSurface(
String8(name.c_str()), w, h, format, flags);
...
surface->incStrong((void *)nativeCreate);
return reinterpret_cast<jlong>(surface.get());
}

frameworks/native/libs/gui/SurfaceComposerClient.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
sp<SurfaceControl> SurfaceComposerClient::createSurface(
const String8& name,
uint32_t w,
uint32_t h,
PixelFormat format,
uint32_t flags)
{
sp<SurfaceControl> sur;
if (mStatus == NO_ERROR) {
sp<IBinder> handle;
sp<IGraphicBufferProducer> gbp;
// 委托给Client进行创建
status_t err = mClient->createSurface(name, w, h, format, flags,
&handle, &gbp);
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
// 将返回的binder句柄与producer引用封装成SurfaceControl返回
sur = new SurfaceControl(this, handle, gbp);
}
}
return sur;
}

到这里,获取到了producer的引用其实Surface就已经创建成功了,我们直接看SurfaceControl是如何获取到Surface的:

frameworks/native/libs/gui/SurfaceControl.cpp

1
2
3
4
5
6
7
8
sp<Surface> SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
mSurfaceData = new Surface(mGraphicBufferProducer, false);
}
return mSurfaceData;
}

可以看到,Surface的创建不过是将producer引用封装到Surface中,本质上客户端是通过producer与surface flinger进程的服务进行通信,真正的绘制相关的操作都是需要跨进程调用到该进程才能够完成

这里稍微深究一下Layer的创建

frameworks/native/services/surfaceflinger/Client.cpp

1
2
3
4
5
6
7
8
9
10
status_t Client::createSurface(
const String8& name,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle,
sp<IGraphicBufferProducer>* gbp)
{
...
result = flinger->createLayer(name, client, w, h, format, flags,
handle, gbp);
}

主要创建操作委托给SurfaceFlinger进行

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
status_t SurfaceFlinger::createLayer(
const String8& name,
const sp<Client>& client,
uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp)
{
...
// 可以看到handle与producer都是在该方法进行创建
result = createNormalLayer(client,
name, w, h, flags, format,
handle, gbp, &layer);
}
status_t SurfaceFlinger::createNormalLayer(const sp<Client>& client,
const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format,
sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
{
// 进行初始化
*outLayer = new Layer(this, client, name, w, h, flags);
status_t err = (*outLayer)->setBuffers(w, h, format, flags);
if (err == NO_ERROR) {
// 获取引用
*handle = (*outLayer)->getHandle();
*gbp = (*outLayer)->getProducer();
}
}

frameworks/native/services/surfaceflinger/Layer.cpp

1
2
3
4
5
6
7
8
9
10
void Layer::onFirstRef() {
// Creates a custom BufferQueue for SurfaceFlingerConsumer to use
sp<IGraphicBufferProducer> producer;
sp<IGraphicBufferConsumer> consumer;
// 创建BufferQueue,同时创建对应的生产者与消费者,每个Layer单独拥有这一套模型
BufferQueue::createBufferQueue(&producer, &consumer);
mProducer = new MonitoredProducer(producer, mFlinger);
mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(consumer, mTextureName);
...
}

frameworks/native/libs/gui/BufferQueue.cpp

1
2
3
4
5
6
7
8
9
10
11
12
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
const sp<IGraphicBufferAlloc>& allocator) {
sp<BufferQueueCore> core(new BufferQueueCore(allocator));
sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core));
sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core));
*outProducer = producer;
*outConsumer = consumer;
}

最终到BufferQueue,整个SurfaceControl的创建操作就完成了。可以看到,这个创建过程为之后的绘制刷新提供了操作环境。其中的生产者引用会通过层层的返回,最终通过WMS返回给App客户端,客户但就可以通过Surface直接与surface flinger进程的服务进行通信,完成视图刷新操作

绘制窗口: ViewRootImpl.drawSoftware

窗口绘制的本质,其实就在于将从Surface中获取到的Canvas进行绘制,如下图:

安卓系统中运行着多个应用,每个应用又可以运行着多个Activity,每个Activity其实本质上拥有着一个父View,即DecorView,它绘制的其实是从ViewRootImpl的Surface中拿到的Canvas

frameworks/base/core/java/android/view/ViewRootImpl.java

1
2
3
4
5
6
7
8
9
10
11
12
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
boolean scalingRequired, Rect dirty) {
...
// 获取一个Canvas
canvas = mSurface.lockCanvas(dirty);
...
// 进行绘制
mView.draw(canvas);
...
// 请求SurfaceFlinger进行绘制
surface.unlockCanvasAndPost(canvas);
}

mView对象是控件树中的root节点,也就是所APP控件中常常获取到的Canvas是从ViewRootImpl中传递过来的

frameworks/base/core/jni/android_view_Surface.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
...
ANativeWindow_Buffer outBuffer;
status_t err = surface->lock(&outBuffer, dirtyRectPtr);
...
// 之后APP会在该Canvas上进行2D图像的绘制
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
nativeCanvas->setBitmap(bitmap);
...
sp<Surface> lockedSurface(surface);
lockedSurface->incStrong(&sRefBaseOwner);
return (jlong) lockedSurface.get();
}

当APP绘制完成后,ViewRootImpl继续调用unlockCanvasAndPost, 之后又会调用回native

frameworks/base/core/jni/android_view_Surface.cpp

1
2
3
4
5
6
7
8
9
10
11
12
static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject canvasObj) {
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
...
// detach the canvas from the surface
Canvas* nativeCanvas = GraphicsJNI::getNativeCanvas(env, canvasObj);
nativeCanvas->setBitmap(SkBitmap());
// unlock surface
status_t err = surface->unlockAndPost();
...
}

frameworks/native/libs/gui/Surface.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
status_t Surface::unlockAndPost()
{
...
int fd = -1;
// 将GraphicBuffer解锁
status_t err = mLockedBuffer->unlockAsync(&fd);
// 将完成绘制的图像buffer入队
err = queueBuffer(mLockedBuffer.get(), fd);
mPostedBuffer = mLockedBuffer;
mLockedBuffer = 0;
return err;
}
int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
...
int i = getSlotFromBufferLocked(buffer);
...
// binder call到运行在surfaceflinger进程中的GraphicBufferProducer
status_t err = mGraphicBufferProducer->queueBuffer(i, input, &output);
...
}

mGraphicBufferProducer的是在Surface初始化时被创建的,是一个binder句柄,通过它可以调用到surface flinger进程中进行图像buffer入列

frameworks/native/libs/gui/BufferQueueProducer.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
status_t BufferQueueProducer::queueBuffer(int slot,
const QueueBufferInput &input, QueueBufferOutput *output) {
...
if (mCore->mQueue.empty()) {
// 如果队列为空,直接将该项插入到队列中
mCore->mQueue.push_back(item);
frameAvailableListener = mCore->mConsumerListener;
} else {
// 如果不为空,就需要检查队列中是否有子项需要被替代
const BufferItem& last = mCore->mQueue.itemAt(
mCore->mQueue.size() - 1);
if (last.mIsDroppable) {
...
// 进行替换
mCore->mQueue.editItemAt(mCore->mQueue.size() - 1) = item;
frameReplacedListener = mCore->mConsumerListener;
} else {
mCore->mQueue.push_back(item);
frameAvailableListener = mCore->mConsumerListener;
}
}
...
}

这个是典型的生产者消费者模式,应用绘制完成后,将会把经过绘制的buffer通过binder call的方式传给运行在surfaceflinger的producer,代替客户端进行消费队列的插入操作。插入完成后,图形缓存去就可以等待consumer来进行消费了。

frameworks/native/libs/gui/BufferQueueConsumer.cpp

1
2
3
4
5
6
7
8
9
status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer,
nsecs_t expectedPresent, uint64_t maxFrameNumber) {
...
BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin());
// 对buffer进行处理
...
// 处理完成后进行移除
mCore->mQueue.erase(front);
}
扫码支持0.99元,您的支持将鼓励我继续创作!