因为我以前接触APP层的视图绘制相关业务比较多,对View的显示相关源码相对来说更感兴趣,所以想写WMS相关的源码解析很久了,但是一直迟迟没有开始写。主要是因为WMS的确是属于Android系统中最复杂的组件之一,知识点涉及从Activity生命周期、Binder、JNI、Native再到SurfaceFlinger等方方面面,分析起来容易陷入无形的大网中迷失方向
之前我有分析过View视图的测量、布局、绘制与Activity的联系,也分析过ViewRootImpl在App客户端的地位,其实就是为了这篇做准备,现在感觉基础的知识点已经具备了。但是一篇博客的内容实在是太难覆盖WMS相关的知识点了, 所以我对其中的代码进行了一定的删减,避免陷入阅读源码细节的囧境
我的目的本身是为了理解WMS在视图绘制的角色,本文中尽量多画图,少列举代码,方便快速的理解App, WMS与SurfaceFlinger的交互模式与流程
视图绘制流程:
frameworks/base/core/java/android/app/ActivityThread.java
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
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
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是窗口相关的控制器,专门用来协调窗口相关的操作
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
@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
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正是主要凭借着它们来组织视图的系统层级结构的
frameworks/base/core/java/android/view/ViewRootImpl.java
void scheduleTraversals(){ if (!mTraversalScheduled) { ... mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null); ... } }
窗口的刷新是由VSYNC进行控制的,主要是通过调用scheduleTraversals方法进行实现,这里可以看到,主要是通过mChoreographer发送了一个Message进行实现的
final class TraversalRunnableimplements 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
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
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
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
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
static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, jstring nameStr, jint w, jint h, jint format, jint flags) { ScopedUtfCharsname(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
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
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
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
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
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
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进程的服务进行通信,完成视图刷新操作
窗口绘制的本质,其实就在于将从Surface中获取到的Canvas进行绘制,如下图:
安卓系统中运行着多个应用,每个应用又可以运行着多个Activity,每个Activity其实本质上拥有着一个父View,即DecorView,它绘制的其实是从ViewRootImpl的Surface中拿到的Canvas
frameworks/base/core/java/android/view/ViewRootImpl.java
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
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
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
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
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
status_t BufferQueueConsumer::acquireBuffer(BufferItem* outBuffer, nsecs_t expectedPresent, uint64_t maxFrameNumber) { ... BufferQueueCore::Fifo::iterator front(mCore->mQueue.begin()); // 对buffer进行处理 ... // 处理完成后进行移除 mCore->mQueue.erase(front); }