本文是Android視圖層源碼分析系列第二篇文章,經過上一篇文章深刻剖析Window組成已經瞭解到WindowManager.addView(contentView)
最終會交給WindowManagerService
處理,WindowManagerService
會建立這個contentView
相關的UI載體Surface
,本文的目的就是理清Surface
的建立過程,以及它與SurfaceFlinger
的關係。java
文章比較長,但但願你能夠堅持看完,相信會有必定收穫的android
本文是基於Google Android Repo中的較新的源碼分析的。Android UI
渲染這一塊變化仍是比較大的,邏輯可能和網上大部分文章有一些出入。git
在本文正式開始以前,咱們先來了解一下與SurfaceFlinger相關的基礎知識:github
SurfaceFlinger
能夠說是Android UI
渲染體系的核心,在Android系統啓動時會啓動SurfaceFlinger
服務,它的主要做用就是被Android應用程序調用,把繪製(測量,佈局,繪製)後的窗口(Surface)渲染到手機屏幕上。因此整個 UI刷新過程可能像下面這張圖:bash
固然實際上的UI渲染原理可沒有像上圖那樣這麼簡單。爲了接下來在源碼追蹤的過程當中不迷路,咱們帶着下面幾個問題來開始分析:微信
ok,接下來就開始Android UI顯示原理之Surface的建立
的主要流程分析。因爲整個體系的源碼流程很複雜,所以在追蹤源碼時我只貼了一些整個流程分析中的主要節點,而且加了一些註釋。session
在上一篇文章中咱們知道,ViewRootImpl
管理着整個view tree。 對於ViewRootImpl.setView()
,咱們能夠簡單的把它當作一個UI渲染操做
的入口,所以咱們就從這個方法開始看:app
ViewRootImpl.javaide
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指針
。那這個對象是怎麼建立的呢?
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指針
第一次使用時會調用下面這個方法:
//這個方法在第一次使用SurfaceComposerClient的指針的時候會調用
void SurfaceComposerClient::onFirstRef() {
....
sp<ISurfaceComposerClient> conn;
//sf 就是SurfaceFlinger
conn = (rootProducer != nullptr) ? sf->createScopedConnection(rootProducer) :
sf->createConnection();
...
}
複製代碼
即經過SurfaceFlinger(它自己具備跨進程通訊的能力)
建立了一個ISurfaceComposerClient
對象:
SurfaceFlinger.cpp
sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
return initClient(new Client(this)); //initClient這個方法其實並無作什麼,
}
複製代碼
即構造了一個Client
對象,Client
實現了ISurfaceComposerClient
接口。是一個能夠跨進程通訊的aidl對象。即SurfaceComposerClient
能夠經過它來和SurfaceFlinger
通訊。除此以外它還能夠建立Surface
,而且維護一個應用程序的全部Layer(下文會分析到它是什麼)
。它是一個十分重要的對象,咱們先來看一下它的組成,它所涉及的其餘東西在下文分析中都會講到:
Client.h
class Client : public BnSurfaceComposerClient
{
public:
...
void attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer);
void detachLayer(const Layer* layer);
...
private:
// ISurfaceComposerClient interface。 gbp很重要,它維護這一個應用程序的渲染 Buffer隊列
virtual status_t createSurface(...sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp);
virtual status_t destroySurface(const sp<IBinder>& handle);
//跨進程通訊方法
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
...
// constant
sp<SurfaceFlinger> mFlinger;
// protected by mLock
DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayers; // 一個應用程序的全部Layer
...
};
複製代碼
通過上面這一頓源碼分析,咱們大概知道了ViewRootImpl.setView()
所引起的主要操做:
WindowManagerService
建立了一個WindowState
。用來表示客戶端的一個Window
WindowManagerService
建立了一個SurfaceSession
,SurfaceSession
會與SurfaceFlinger
構建連接,建立了一個SurfaceComposerClient
對象,一個應用程序只具備一個這個對象。SurfaceComposerClient
建立了一個Client
, 這個對象十分重要,它維護這應用程序的渲染核心數據,並負責與SurfaceFlinger
通訊。以下圖:
通過上面的步驟,應用程序的ViewRootImpl
已經被WindowManagerService
識別,而且應用程序已經與SurfaceFlinger
創建鏈接。即建立了SurfaceComposerClient
和Client
對象
文章開始就已經說了Surface
是Window(ViewRootImpl)
的UI載體,那Surface
是在哪裏建立的呢?
其實一個ViewRootImpl
就對應一個Surface
。這點能夠經過ViewRootImpl
的源碼看出:
ViewRootImpl.java
public final Surface mSurface = new Surface();
複製代碼
即ViewRootImpl
在構造的時候就new 了一個 Surface
。但其實這個新new的Surface
並無什麼邏輯,它的構造函數是空的。那麼Surface
究竟是在哪裏建立的呢?
咱們仍是回到ViewRootImpl.setView()
來看一下:
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
requestLayout(); //susion 請求layout。先添加到待渲染隊列中
...
res = mWindowSession.addToDisplay(mWindow, ...); //WindowManagerService會建立mWindow對應的WindowState
...
}
複製代碼
即在向WindowManagerService
請求建立WindowState
以前,調用了requestLayout()
,這個方法會引發ViewRootImpl
所管理的整個view tree的從新渲染。它最終會調用到scheduleTraversals()
:
void scheduleTraversals() {
...
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
...
}
複製代碼
對於Choreographer
本文不作詳細的分析,能夠去參考 Android Choreographer 源碼分析的分析來了解這個類。
scheduleTraversals()
會經過Choreographer
來post一個mTraversalRunnable
,Choreographer
接收顯示系統的時間脈衝(垂直同步信號-VSync信號,16ms發出一次),在下一個frame渲染時控制執行這個mTraversalRunnable
。
可是mTraversalRunnable
的執行至少要在應用程序與SurfaceFlinger
創建鏈接以後。這是由於渲染操做是由SurfaceFlinger
負責調度了,若是應用程序尚未與SurfaceFlinger
建立鏈接,那SurfaceFlinger
固然不會渲染這個應用程序。因此在執行完mWindowSession.addToDisplay(mWindow, ...)
以後,纔會執行mTraversalRunnable
:
ViewRootImpl.java
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
複製代碼
doTraversal()
會調用到ViewRootImpl.performTraversals()
,大部分同窗可能知道這個方法是一個view tree
的measure/layout/draw
的控制方法:
private void performTraversals() {
finalView host = mView; //mView是一個Window的根View,對於Activity來講就是DecorView
...
relayoutWindow(params, viewVisibility, insetsPending);
...
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
...
performLayout(lp, mWidth, mHeight);
...
performDraw();
...
}
複製代碼
Surface
的具體建立就由relayoutWindow(params, viewVisibility, insetsPending)
這個方法來完成的。這個方法會經過IPC
調用到WindowManagerService.relayoutWindow()
:
ViewRootImpl.java
private int relayoutWindow(WindowManager.LayoutParams params, ...) throws RemoteException {
...
int relayoutResult = mWindowSession.relayout(mWindow,..., mSurface);
...
}
複製代碼
上面我省略了mWindowSession.relayout()
方法的不少參數,不過有一個十分重要的參數我沒有省略,就是mSurface
。前面已經分析了它就是一個空的Surface
對象。其實:
真正的Surface建立是由SurfaceControl
完成的,應用程序ViewRootImpl
的Surface
只是一個指針,指向這個Surface
下面就來看一下SurfaceControl
是如何建立Surface
的:
mWindowSession.relayout()
會調用到WindowManagerService.relayoutWindow()
:
WindowManagerService.java
//這裏的outSurface其實就是ViewRootImpl中的那個Surface
public int relayoutWindow(Session session, IWindow client....Surface outSurface){
...
result = createSurfaceControl(outSurface, result, win, winAnimator);
...
}
private int createSurfaceControl(Surface outSurface, int result, WindowState win,WindowStateAnimator winAnimator) {
...
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
...
surfaceController.getSurface(outSurface);
}
複製代碼
winAnimator.createSurfaceLocked
其實是建立了一個SurfaceControl
。即上面是先構造SurfaceControl
,而後在構造Surface
。
winAnimator.createSurfaceLocked
實際上是經過SurfaceControl
的構造函數建立了一個SurfaceControl
對象,這個對象的做用其實就是負責維護Surface
,Surface
其實也是由這個對象負責建立的,咱們看一下這個對象的構造方法:
SurfaceControl.java
long mNativeObject; //成員指針變量,指向native建立的SurfaceControl
private SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
SurfaceControl parent, int windowType, int ownerUid){
...
mNativeObject = nativeCreate(session, name, w, h, format, flags,
parent != null ? parent.mNativeObject : 0, windowType, ownerUid);
...
}
複製代碼
即調用了nativeCreate()
並返回一個SurfaceControl
指針:
android_view_SurfaceControl.cpp
static jlong nativeCreate(JNIEnv* env, ...) {
//這個client其實就是前面建立的SurfaceComposerClinent
sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
sp<SurfaceControl> surface; //建立成功以後,這個指針會指向新建立的SurfaceControl
status_t err = client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface, flags, parent, windowType, ownerUid);
...
return reinterpret_cast<jlong>(surface.get()); //返回這個SurfaceControl的地址
}
複製代碼
即調用到SurfaceComposerClient.createSurfaceChecked()
:
SurfaceComposerClient.cpp
//outSurface會指向新建立的SurfaceControl
status_t SurfaceComposerClient::createSurfaceChecked(...sp<SurfaceControl>* outSurface..)
{
sp<IGraphicBufferProducer> gbp; //這個對象很重要
...
err = mClient->createSurface(name, w, h, format, flags, parentHandle, windowType, ownerUid, &handle, &gbp);
if (err == NO_ERROR) {
//SurfaceControl建立成功, 指針賦值
*outSurface = new SurfaceControl(this, handle, gbp, true);
}
return err;
}
複製代碼
上面這個方法其實是調用Client.createSurface()
來建立一個Surface
。在建立時有一個很重要的參數sp<IGraphicBufferProducer> gbp
,在下面源碼分析中咱們也要重點注意它。這是由於應用所渲染的每一幀,實際上都會添加到IGraphicBufferProducer
中,來等待SurfaceFlinger
的渲染。這個過程咱們在下一篇文章中會分析,咱們先繼續來看一下Surface
是如何被Client
建立的:
Client.cpp
status_t Client::createSurface(...)
{
...
//gbp 直接透傳到了SurfaceFlinger
return mFlinger->createLayer(name, this, w, h, format, flags, windowType, ownerUid, handle, gbp, &parent);
}
複製代碼
??? 不是說好的要建立Surface
呢?怎麼變成mFlinger->createLayer()
? 額,我也不明白這個忽然轉變,不過咱們只要知道:
Surface
在SurfaceFlinger
中對應的實體實際上是Layer
咱們繼續看一下mFlinger->createLayer()
SurfaceFlinger.cpp
status_t SurfaceFlinger::createLayer(const String8& name,const sp<Client>& client...)
{
status_t result = NO_ERROR;
sp<Layer> layer; //將要建立的layer
switch (flags & ISurfaceComposerClient::eFXSurfaceMask) {
case ISurfaceComposerClient::eFXSurfaceNormal:
result = createBufferLayer(client,
uniqueName, w, h, flags, format,
handle, gbp, &layer); // 注意gbp,這時候尚未構造呢!
break;
... //Layer 分爲好幾種,這裏不所有列出
}
...
result = addClientLayer(client, *handle, *gbp, layer, *parent); //這個layer和client相關聯, 添加到Client的mLayers集合中。
...
return result;
}
複製代碼
從SurfaceFlinger.createLayer()
方法能夠看出Layer
分爲好幾種。咱們這裏只對普通的BufferLayer
的建立作一下分析,看createBufferLayer()
:
status_t SurfaceFlinger::createBufferLayer(const sp<Client>& client... sp<Layer>* outLayer)
{
...
sp<BufferLayer> layer = new BufferLayer(this, client, name, w, h, flags);
status_t err = layer->setBuffers(w, h, format, flags); //設置layer的寬高
if (err == NO_ERROR) {
*handle = layer->getHandle(); //建立handle
*gbp = layer->getProducer(); //建立 gbp IGraphicBufferProducer
*outLayer = layer; //把新建的layer的指針拷貝給outLayer,這樣outLayer就指向了新建的BufferLayer
}
return err;
}
複製代碼
前面我說過IGraphicBufferProducer(gbp)
是一個很重要的對象,它涉及到SurfaceFlinger
的渲染邏輯,下面咱們就看一下這個對象的建立邏輯:
BufferLayer.cpp
sp<IGraphicBufferProducer> BufferLayer::getProducer() const {
return mProducer;
}
複製代碼
即mProducer
實際上是Layer
的成員變量,它的建立時機是Layer
第一次被使用時:
void BufferLayer::onFirstRef() {
...
BufferQueue::createBufferQueue(&producer, &consumer, true);
mProducer = new MonitoredProducer(producer, mFlinger, this);
...
}
複製代碼
因此mProducer
的實例是MonitoredProducer
,但其實它只是一個裝飾類,它實際功能都委託給構造它的參數producer
:
BufferQueue.cpp
void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
...
sp<IGraphicBufferProducer> producer(new BufferQueueProducer(core, consumerIsSurfaceFlinger));
sp<IGraphicBufferConsumer> consumer(new BufferQueueConsumer(core)); //注意這個consumer
...
*outProducer = producer;
*outConsumer = consumer;
}
複製代碼
因此實際實現mProducer
的工做的queueProducer
是BufferQueueProducer
。
因此構造一個SurfaceControl
所作的工做就是建立了一個SurfaceControl
,並讓SurfaceFlinger
建立了一個對應的Layer
,Layer
中有一個IGraphicBufferProducer
,它的實例是BufferQueueProducer
。
能夠用下面這個圖來描述SurfaceControl
的建立過程:
咱們回看WindowManagerService.createSurfaceControl()
, 來看一下java層的Surface
對象究竟是個什麼:
WindowManagerService.java
private int createSurfaceControl(Surface outSurface, int result, WindowState win,WindowStateAnimator winAnimator) {
...
surfaceController = winAnimator.createSurfaceLocked(win.mAttrs.type, win.mOwnerUid);
...
surfaceController.getSurface(outSurface);
}
複製代碼
上面咱們已經瞭解了winAnimator.createSurfaceLocked
的整個過程,咱們看一下surfaceController.getSurface(outSurface)
, surfaceController
是WindowSurfaceController
的實例:
//WindowSurfaceController.java
void getSurface(Surface outSurface) {
outSurface.copyFrom(mSurfaceControl);
}
//Surface.java
public void copyFrom(SurfaceControl other) {
...
long surfaceControlPtr = other.mNativeObject;
...
long newNativeObject = nativeGetFromSurfaceControl(surfaceControlPtr);
...
mNativeObject = ptr; // mNativeObject指向native建立的Surface
}
複製代碼
即Surface.copyFrom()
方法調用nativeGetFromSurfaceControl()
來獲取一個指針,這個指針是根據前面建立的SurfaceControl
的指針來尋找的,即傳入的參數surfaceControlPtr
:
android_view_Surface.cpp
static jlong nativeGetFromSurfaceControl(JNIEnv* env, jclass clazz, jlong surfaceControlNativeObj) {
sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj)); //把java指針轉化內native指針
sp<Surface> surface(ctrl->getSurface()); //直接構造一個Surface,指向 ctrl->getSurface()
if (surface != NULL) {
surface->incStrong(&sRefBaseOwner); //強引用
}
return reinterpret_cast<jlong>(surface.get());
}
複製代碼
這裏的ctrl
指向前面建立的SurfaceControl
,繼續追溯ctrl->getSurface()
:
SurfaceControl.cpp
sp<Surface> SurfaceControl::getSurface() const
{
Mutex::Autolock _l(mLock);
if (mSurfaceData == 0) {
return generateSurfaceLocked();
}
return mSurfaceData;
}
sp<Surface> SurfaceControl::generateSurfaceLocked() const
{
//這個mGraphicBufferProducer其實就是上面分析的BufferQueueProducer
mSurfaceData = new Surface(mGraphicBufferProducer, false);
return mSurfaceData;
}
複製代碼
即直接new了一個nativie的Surface
返回給java層,java層的Surface
指向的就是native層的Surface
。
因此Surface
的實際建立能夠用下圖表示:
通過上面這個圖,也能夠理解SurfaceControl
爲何叫SurfaceControl
了。
本文到這裏已經很長了,對於UI的渲染過程:即ViewRootImpl是如何渲染到Surface到下一篇文章再分析。
歡迎關注個人Android進階計劃看更多幹貨
歡迎關注個人微信公衆號:susion隨心
參考文章: