本篇針對Surface模塊進行分析,從Java層的Activity建立開始,到ViewRoot、WindowsManagerService,再到JNI層和Native層。java
首先推薦一個Android源碼查看的網站:http://androidxref.com/android
Surface的建立涉及三個部分:canvas
App 進程
App須要將本身的內容顯示在屏幕上,因此App負責發起Surface建立請求,建立好Surface後, 就能夠直接能夠在canvas上畫圖等,最終都會保存到Surface裏的buffer裏,最後由SurfaceFlinger合成並顯示。數組
System_Server進程
主要是其中的WindowManagerService, 負責接收APP請求,向SurfaceFlinger發起具體的請求建立Surface, 且WMS須要建立Surface的輔助管理類,如SurfaceControl。session
SurfaceFlinger
爲App進程建立具體的Surface, 在SurfaceFlinger裏對應成Layer, 而後負責管理、合成顯示。app
整體流程(參考《深刻理解Android》,源碼較舊):composer
Surface建立過程: ActivityThread.java 調用handleLaunchActivity 調用handleResumeActivity函數 addView調用到LocalWindowManager.java的addView函數 而後調用WindowManagerImpl.java的addView函數 建立ViewRoot(分紅兩個分支): 1、執行ViewRoot的構造函數,建立mSurface(!實現ViewRoot的Surface建立)(建立IWindow) 2、調用ViewRoot的setView函數(分紅兩個分支): 1、setView調用WMS的add函數(IWindowSession) 調用WMS的addWindow函數 調用WMS.java::WindowState的attach函數 調用WMS.java::Session的windowAddedLocked函數,建立SurfaceSession(!實現WMS的SurfaceSession建立) 執行SurfaceSession的構造器,調用native函數init JNI層實現init函數,建立一個SurfaceComposerClient(分紅兩步): 1、SurfaceComposerClient構造函數調用SurfaceFlinger的createConnection(!和SF創建交互通道) 建立Client(建立共享內存)(一個Client最多支持31個顯示層) Client構造函數建立SharedClient對象 SharedClient定義SharedBufferStack數組對象(有31個元素) 建立BClient(接受客戶端請求,將處理提交給SF) 2、再調用_init(初始化SurfaceComposerClient一些成員變量) 2、調用requestLayout函數,向ViewRoot發送DO_TRAVERSAL消息 調用handleMessage函數 調用performTraversal函數(分紅兩個分支): 1、調用ViewRoot的relayoutWindow函數(調用IWindowSession的relayout函數) 調用createSurfaceControl建立一個SurfaceControl ?在SurfaceComposerClient的createSurface建立一個SurfaceControl(請求端) ?SurfaceComposerClient調用createSurface建立一個Surface(SurfaceControl類型) ? 調用SurfaceControl的writeToParcel將信息寫入Parcel包中 ? 在readFromParcel中經過Parcel信息構造一個Surface對象,保存到mSurface ? ViewRoot得到一個Native的Surface對象 調用WMS.java::Session的relayout函數(!此和上這兩步跨進程)(分紅三步): 1、在IWindowSession.adil的Bn端調用onTransact,writeToParcel寫入信息 2、在IWindowSession.adil的Bp端,relayout中傳入outSurface,readFormParcel讀取信息填充outSurface 3、調用WMS的relayoutWindow 》》調用WMS.java::WindowState的createSurfaceLocked,建立本地Surface(SurfaceSession) 》》調用copyForm,將本地surface信息拷貝到outSurface(即mSurface) 2、調用draw()函數開始繪製(lockCanvas、調用draw、unlockCanvasAndPost) 調用DecorView的draw函數(!實現UI繪製)
Surface和APP的關係:tcp
Surface像是UI的畫布,APP就像是在Surface上做畫,經過i使用Skia繪製二維圖像,或是用OpenGL繪製三維圖像,最終APP和Surfacea都要進行交互。ide
SUrface和SurfaceFlinger(SF)的關係:函數
surface向SF提供數據,SF進行混合數據。
一、應用程序的顯示和surface有關,而應用程序的外表經過Activity展現的,那麼Activity如何建立的呢?
App對應的進程,它的入口函數是ActivityThread類的main函數。
ActivityThread類中有一個handleLaunchActivity函數(建立Activity),代碼以下:
private void handleLaunchActivity(ActivityClientRecord r , Intent customIntent , String reason) { ... Activity a = performLaunchActivity(r, customIntent); ... if (a != null) { ... handleResumeActivity(r.token , false , r.isForward ,!r.activity.mFinished && !r.startsNotResumed , r.lastProcessedSeq, reason); //Activity建立成功就往onResume()走了! ... } }
這個函數涉及了兩個關鍵函數:
(1)performLaunchActivity
返回一個activity(即App中的Activity),該方法 建立了Activity:
private Activity performLaunchActivity(ActivityClientRecord r , Intent customIntent) { ... // newActivity函數根據Activity的類名經過Java反射機制建立對應的Activity activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); ... Application app = r.packageInfo.makeApplication(false , mInstrumentation); //在獲取Application ... activity.attach(appContext , this , getInstrumentation() , r.token ,.ident , app , r.intent , r.activityInfo , title , r.parent , r.embeddedID , r.lastNonConfigurationInstances , config ,r.referrer , r.voiceInteractor , window); ... if (r.isPersistable()) { mInstrumentation.callActivityOnCreate( activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); //調用Activity的onCreate函數 } ...
}
所以,performLaunchActivity的做用以下:
(2)handleResumeActivity
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume) { ... // 與調用Activity的onResume相關 ActivityClientRecord r = performResumeActivity(token, clearHide); ... // PhoneWindow r.window = r.activity.getWindow(); // 獲取Activity的DecorView View decor = r.window.getDecorView(); decor.setVisibility(View.INVISIBLE); // WindowManagerImpl,其實就是LocalWindowManager ViewManager wm = a.getWindowManager(); WindowManager.LayoutParams l = r.window.getAttributes(); a.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; if (a.mVisibleFromClient) { a.mWindowAdded = true; wm.addView(decor, l); // 將剛纔的dector對象加入到ViewManagerg中 } ... }
> 在Activity.java中Activity在onCreate函數中經過setContentView設置UI界面。
Activity.java部分代碼:
public void setContentView(View view) { getWindow().setContentView(view); // 傳入一個view } public Window getWindow() { return mWindow; //返回一個類型爲Window的對象 }
> 分析出現的兩個和UI相關的類:
Window:一個抽象基類,用於控制頂層窗口的外觀和行爲。職能多是繪製背景、標題欄、默認的按鍵處理等。
它將做爲一個頂層的view加入到Window Manager中。
View:一個基本的UI單元,佔據屏幕的一塊矩形區域,可用於繪製,能處理事件。(設置的view其實只是DecorView的子view,DecorView還處理了標題欄顯示等一系列操做)
也能夠看作:
> 分析addView,wm類型其實是LocalWindowManager,查看LocalWindowManager.java的addView函數:
public final void addView(View view , ViewGroup.LayoutParams params) { .............. mWindowManager.addView(view, params); // mWindowManager對象實際是WindowManagerImpl類型 }
接着查看WindowManagerImpl.java類的addView函數:
private void addView(View view, ViewGroup.LayoutParams params, boolean nest) { ... ViewRoot root; ... root = new ViewRoot(view.getContext()); // 建立viewRoot ... ①root.setView(view, wparams, panelParentView); // view即剛剛介紹的DectorView }
二、 viewRoot: viewRoot實現了ViewParent接口,ViewParent不處理繪畫,由於它沒有onDraw函數(因此和Android基本繪畫單元的view不太同樣)
//查看ViewRoot.java::ViewRoot定義 public final class ViewRoot extends Handler implements ViewParent, View.AttachInfo.Callbacks // 從Handler 派生 { private final Suface mSurface = new Surface(); // 建立了一個Surface 對象 Final W mWindow; View mView; }
分析得出ViewRoot的做用:
View、DectorView是UI單元,繪畫工做在OnDraw函數中完成。若是onDraw是畫圖過程,那麼畫布就是Surface。
Surface:有一塊Raw Buffer,Surface操做這塊Raw Buffer,Screen Compositor(即SurfaceFlinger)管理這塊Raw Buffer。
結論:
在①的setView中,調用的時ViewRoot.java的setView函數:
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { ... ... res = sWindowSession.add(mWindow, mWindowAttributes, getHostVisibility(), mAttachInfo.mContentInsets, mInputChannel); ... }
實現了:
三、requestLayout會向ViewRoot發送一個消息,進入ViewRoot.java的handleMessage函數,調用performTraversals函數。
進入 performTraversals函數:
private void performTraversals() { final View host = mView; //即最初的DectorView ...
try{
relayoutResult = relayoutWindow(params, viewVisiblity, insetPending);
} ... host.measure(childWidthMeasureSpec, childHeightMeasureSpec); ... host.layout(0, 0, host.mMeasuredWidth, host.mMeasuredHeight); ... ... draw(fullRedrawNeeded); ... }
(1)relayoutWindow函數:會調用IWindowSession的Relayout函數;
(2)draw函數:從mSurface(Surface)中lock一塊Canvas(畫布),調用DecorView的draw函數,而後交給mView繪畫,最後unlockCanvasAndPost釋放這塊Canvas
總結:
一、大體涉及的方法、類的大致流程(回車表示前一方法內調用):
ActivityThread.java
調用handleLaunchActivity
調用performLaunchActivity函數(建立Activity、調用onCreate)
onCreate調用setContentView函數設置UI界面,傳入view,返回Window
調用handleResumeActivity函數
addView調用到LocalWindowManager.java的addView函數
而後調用WindowManagerImpl.java的addView函數
建立ViewRoot,調用ViewRoot的setView函數
ViewRoot.java(繼承Handler、實現ViewParent)
構造函數建立一個Surface對象mSurface
setView函數實現:
保存傳入的view爲mView
調用requestLayout
調用IWindowSession的add函數
WIndowManagerServce.java::session的add函數
調用WMS.java的addWindow
調用WMS.java::WIndowState的attach函數
調用windowAnddedLocked函數並建立一個SurfaceSession對象
requestLayout(向ViewRoot發送一個消息)
進入ViewRoot.java的handleMessage函數
調用performTraversals函數
調用relayoutWindow函數
調用IWindowSession的Relayout函數
調用draw函數(從mSurface中lock一塊Canvas)
調用DecorView的draw函數,交給mView繪畫
最後unlockCanvasAndPost釋放Canvas
二、要點:
(1)整個Activity的繪圖流程就是從mSurface中lock一塊Canvas,而後交給mView去繪畫,最後unlockCanvasAndPost釋放這塊Canvas ;
(2)Activity的頂層view是DecotView,而onCreate函數中setContentView設置的View是這個DecorView的一部分。DecorView是一個FrameLayout類型的ViewGroup;
(3)Activity和UI有關,包含window(真實類型是phoneWIndow)和一個WindowManger(真實類型是LocalWindowManager)對象。這兩個對象控制整個Activity的顯示;
(4)LocalWindowManager使用了WindowManagerImpl.java(其中addView有一個ViewRoot對象)做爲最終處理對象;
(5)ViewRoot實現了ViewParent接口,有兩個變量:
mView,指向Activity頂層UI單元的DecorView
mSurface,包含一個Canvas
此外,ViewRoot還經過Binder系統和dWinowManagerService進行跨進程交互;
(6)ViewRoot可以處理Handler的消息,Activity的顯示就是由ViwRoot在他的performTraversals函數中完成;
經過上面一節的分析可知:
ViewRoot的構造函數裏面會建立一個Surface;
而ViewRoot經過IWindowSession和WMS交互時,WMS調用的attach函數會構造一個SurfaceSession;
ViewRoot在prformTransval的處理過程當中會調用IWindowSession的relayout函數。(WMS由SYsytem_server進程啓動,SF服務也在這個進程中)
兩個部分的Surface看似是毫無關係,可是實際上,在使用createSurfaceLocked() 的時候,會將creaeSurfaceLocked 建立的Surface copy到ViewRoot層的Surface中。也就是這樣,將底層的Surface對象傳到上層,供Activity的界面部分使用,用來繪圖。整個流程大概是:
RootView.relayoutWindow,調用方,調用relayout將mSurface傳進去
-> WindowManagerService.Session.relayout調用外部類對象的relayoutWindow
-> WindowManagerService.relayoutWindow,調用createSurfaceLocked
-> WindowManagerService.createSurfaceLocked(),將SurfaceSession拷貝到建立的新對象Surface
-> outSurface.copyFrom(surface),將本地Surface 的信息(即SurfaceSession)拷貝到outSurface中
最後一步是將WindowManagerService的surface與ViewRoot 的outSurface聯繫起來的關鍵點,outSurface是做爲參數,從RootView傳到WindowManagerService的。
ViewRoot實際上是經過Binder與WindowManagerService進行跨進程調用通訊的。
一、在JNI層,首先被調用的時Surface的無參構造函數,代碼:
// Surface.java Public Surface() { ... mCanvas = new CompatibleCanvas(); // CompatibleCanvaso從Canvas類派生 }
Canvas:
畫圖須要:
通常狀況下,Canvas會封裝一塊Bitmap。
二、SurfaceSession的構造
// SurfaceSession.java public SurfaceSession(){ init(); //這是一個native函數 }
init函數的實如今JNI的android_view_Surface.cpp中:
static void SurfaceSession_init(JNIEnv* env,jobject clazz) { //建立一個SurfaceComposerClient對象 sp<SurfaceComposerClient> client = new SurfaceComposerClient; client->incStrong(clazz); //在Java對象中保存這個client對象的指針,類型爲SurfaceComposerClient env->SetIntField(clazz, sso.client, (int)client.get()); }
三、Surface的有參構造函數:
// Surface.java publicSurface(SurfaceSession s,//傳入一個SurfaceSession對象 int pid, String name, int display, int w, int h, int format, int flags) throws OutOfResourcesException { ...... mCanvas = new CompatibleCanvas(); //又一個native函數,注意傳遞的參數:display之後再說,w,h表明繪圖區域的寬高值 init(s,pid,name,display,w,h,format,flags); mName = name; }
Surface的init函數實如今JNI層:
static void Surface_init( JNIEnv*env, jobject clazz, jobject session, jint pid, jstring jname, jint dpy, jint w, jint h, jint format, jintflags) { //從SurfaceSession對象中取出以前建立的那個SurfaceComposerClient對象 SurfaceComposerClient* client = (SurfaceComposerClient*)env->GetIntField(session, sso.client); sp<SurfaceControl> surface;//注意它的類型是SurfaceControl if (jname == NULL) { /* 調用SurfaceComposerClient的createSurface函數,返回的surface是一個 SurfaceControl類型。 */ surface = client->createSurface(pid, dpy, w, h, format, flags); } else{ ...... } //把這個surfaceControl對象設置到Java層的Surface對象中,對這個函數就再也不分析了 setSurfaceControl(env, clazz, surface); }
四、copyForm分析
上一節中,outSurface.copyFrom(surface),將本地Surface 的信息(即SurfaceSession)拷貝到outSurface中
他是一個native函數,代碼以下:
static void Surface_copyFrom(JNIEnv* env,jobject clazz, jobject other) { //根據JNI函數的規則,clazz是copyFrom的調用對象,而other是copyFrom的參數。 //目標對象此時尚未設置SurfaceControl,而源對象在前面已經建立了SurfaceControl constsp<SurfaceControl>& surface = getSurfaceControl(env, clazz); constsp<SurfaceControl>& rhs = getSurfaceControl(env, other); if (!SurfaceControl::isSameSurface(surface, rhs)) { //把源SurfaceControl對象設置到目標Surface中。 setSurfaceControl(env, clazz, rhs); } }
五、writeToParcel和readFromParcel分析
這兩個函數調用發生在ViewRoot調用IWindowSession的relayout函數中,它發生在IWindowSession.adil(經過aidl -l ...編譯成java文件可查看到relayout方法中和onTransactg中)
// android_view_Surface.cpp static void Surface_writeToParcel(JNIEnv* env,jobject clazz, jobject argParcel, jint flags) { Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel); //clazz就是Surface對象,從這個Surface對象中取出保存的SurfaceControl對象 const sp<SurfaceControl>&control(getSurfaceControl(env, clazz)); /* 把SurfaceControl中的信息寫到Parcel包中,而後利用Binder通訊傳遞到對端, 對端經過readFromParcel來處理Parcel包。 */ SurfaceControl::writeSurfaceToParcel(control, parcel); if (flags & PARCELABLE_WRITE_RETURN_VALUE) { //lags的值就等於PARCELABLE_WRITE_RETURN_VALUE //因此本地Surface對象的SurfaceControl值被置空了 setSurfaceControl(env, clazz, 0); } } --------------------- // android_view_Surface.cpp static void Surface_readFromParcel( JNIEnv* env, jobject clazz, jobject argParcel) { Parcel* parcel = (Parcel*)env->GetIntField( argParcel,no.native_parcel); //注意下面定義的變量類型是Surface,而不是SurfaceControl const sp<Surface>&control(getSurface(env, clazz)); //根據服務端傳遞的Parcel包來構造一個新的surface。 sp<Surface> rhs = new Surface(*parcel); if (!Surface::isSameSurface(control, rhs)) { //把這個新surface賦給ViewRoot中的mSurface對象 setSurface(env,clazz, rhs); } }
小結:
在JNIe層建立了三個對象:SurfaceComposerClient、SurfceControl、Surface
大體流程:
(1)建立一個SurfaceComposerClient
(2)調用SurfaceComposerClient的createSurface獲得一個SurfceControl對象
(3)調用SurfaceControl的writeToParcel,將一些信息寫入Parcel包中
(4)根據Parcel包的信息z構造一個Surface對象,將其保存到Java層的mSurface中
(5)所以,ViewRoot獲得一個Native的Surface對象
Surface和畫圖Canvas:
在ViewRoot的draw()函數裏面(前面有提到),有兩個和Surface相關的函數調用:
(1)lockCanvas:先得到一塊存儲區域,而後將它和Canvas綁定到一塊兒,這樣,UI繪畫的結果就記錄在這塊存儲區域裏了,如此進Canvas進行UI畫圖就會有畫布了;
(2)unlockCanvasAndPost:一個native函數,取出Native的Surface對象,調用Surface的unlockAndPost函數。
調用流程總結:
總結:
一、一個Activity通常都會對應到一個Window, 對應了一個DecorView, ViewRoot
二、ViewRoot中有一個Surface, 就是App能夠用於繪製UI的Surface了,在Native層也對應了一個Surface, 在SurfaceFlinger對應的是一個Layer,經過Layer中的Producer能夠真正的申請Buffer用於繪製。App中經過Surface中的Canvas的相似lockcanvas接口觸發dequeue buffer流程。
三、 一個ViewRoot在WMS端對應了一個WindowState, WindowState又經過一系列引用關聯到一個SurfaceControl, Native層也有一個SurfaceControl。這個能夠用於控制窗口的一些屬性。
四、 WMS native層的SurfaceComposerClient與SurfaceFlinger之間經過ISurfaceComposerClient創建聯繫。一個App在SurfaceFlinger端對應了一個Client,用於處理該App layer的建立等請求。
五、當ViewRootImpl請求WMS relayout時,會將ViewSurface中的Surface交給WMS初始化。在WMS中,對應每一個WindowState對象,在relayout窗口時,一樣會建立一個Surface,wms中的這個Surface會真正的初始化,而後再將這個WMS Surface複製給ViewRootImpl中的Surface。這麼實現的目的就是保證ViewRootImpl和WMS共享同一個Surface。ViewRootImpl對Surface進行繪製,WMS對這個Surface進行初始化及管理。
ActivityThread.java
調用handleLaunchActivity
調用performLaunchActivity函數(建立Activity、調用onCreate)
onCreate調用setContentView函數設置UI界面,傳入view,返回Window
調用handleResumeActivity函數
addView調用到LocalWindowManager.java的addView函數
而後調用WindowManagerImpl.java的addView函數
建立ViewRoot,調用ViewRoot的setView函數
ViewRoot.java(繼承Handler、實現ViewParent)
構造函數建立一個Surface對象mSurface
setView函數實現:
保存傳入的view爲mView
調用requestLayout
調用IWindowSession的add函數
WIndowManagerServce.java::session的add函數
調用WMS.java的addWindow
調用WMS.java::WIndowState的attach函數
調用windowAnddedLocked函數並建立一個SurfaceSession對象
requestLayout(向ViewRoot發送一個消息)
進入ViewRoot.java的handleMessage函數
調用performTraversals函數
調用relayoutWindow函數
調用IWindowSession的Relayout函數
調用draw函數(從mSurface中lock一塊Canvas)
調用DecorView的draw函數,交給mView繪畫
最後unlockCanvasAndPost釋放Canvas
在應用啓動時,會經過WindowManagerGlobal去添加view,添加view時會去建立viewRootImpl,而後進行設置view。
viewRootImpl.setView() —> requestLayout()申請佈局—>scheduleTraversals()—>doTraversal()–>performTraversals()
利用IWindowSession和Session通訊,調用relayout,注意,這裏mSurface是ViewRootImpl的成員變量,開始調用了無參的構造函數,IWindowSession.aidl文件中,參數mSurface是被out修飾,用來接受在server端建立Surface,而後再binder返回給ViewRootImpl。
public int relayout(IWindow window, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewFlags, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { int res = mService.relayoutWindow(this, window, seq, attrs, requestedWidth, requestedHeight, viewFlags, flags, outFrame, outOverscanInsets, outContentInsets, outVisibleInsets, outConfig, outSurface); return res; }
public int relayoutWindow(Session session, IWindow client, int seq, WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, int flags, Rect outFrame, Rect outOverscanInsets, Rect outContentInsets, Rect outVisibleInsets, Configuration outConfig, Surface outSurface) { //新建一個SurfaceControl SurfaceControl surfaceControl = winAnimator.createSurfaceLocked(); if (surfaceControl != null) { outSurface.copyFrom(surfaceControl); if (SHOW_TRANSACTIONS) Slog.i(TAG, " OUT SURFACE " + outSurface + ": copied"); } else { // For some reason there isn't a surface. Clear the // caller's object so they see the same state. outSurface.release(); } }
首先建立一個SurfaceControl:
SurfaceControl createSurfaceLocked() { mSurfaceControl = new SurfaceControl( mSession.mSurfaceSession, attrs.getTitle().toString(), w, h, format, flags); } public SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags) throws OutOfResourcesException { //session就是SurfaceComposerClient在java層的表明 //mNativeObject是native層SurfaceControl的指針 mNativeObject = nativeCreate(session, name, w, h, format, flags); }
static jint nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj, jstring nameStr, jint w, jint h, jint format, jint flags) { ScopedUtfChars name(env, nameStr); //從上層取到SurfaceComposerClient的指針,還原一個SurfaceComposerClient sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj)); //調用createSurface,返回的是一個SurfaceControl對象,注意不是surface sp<SurfaceControl> surface = client->createSurface( String8(name.c_str()), w, h, format, flags); if (surface == NULL) { jniThrowException(env, OutOfResourcesException, NULL); return 0; } surface->incStrong((void *)nativeCreate); //返回給java層SurfaceControl的指針 return int(surface.get()); }
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; status_t err = mClient->createSurface(name, w, h, format, flags, &handle, &gbp); //gbp就是surfacefligner中Layer的mBufferQueue的client端(IGraphicBufferProducer) if (err == NO_ERROR) { sur = new SurfaceControl(this, handle, gbp); } } return sur; }
經過ISurfaceComposerClient的binder通訊,調用服務端對應client對象的方法createSurface():
status_t Client::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) { /* * createSurface must be called from the GL thread so that it can * have access to the GL context. */ class MessageCreateLayer : public MessageBase { SurfaceFlinger* flinger; Client* client; sp<IBinder>* handle; sp<IGraphicBufferProducer>* gbp; status_t result; const String8& name; uint32_t w, h; PixelFormat format; uint32_t flags; public: MessageCreateLayer(SurfaceFlinger* flinger, const String8& name, Client* client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) : flinger(flinger), client(client), handle(handle), gbp(gbp), name(name), w(w), h(h), format(format), flags(flags) { } status_t getResult() const { return result; } //MessageQueue.cpp 中方法回調MessageBase::handleMessage virtual bool handler() { result = flinger->createLayer(name, client, w, h, format, flags, handle, gbp); return true; } }; sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(), name, this, w, h, format, flags, handle, gbp); mFlinger->postMessageSync(msg); return static_cast<MessageCreateLayer*>( msg.get() )->getResult(); }
上述可看出,將建立layer消息放入隊列,以下所示:
status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg, nsecs_t reltime, uint32_t /* flags */) { status_t res = mEventQueue.postMessage(msg, reltime); if (res == NO_ERROR) { //阻塞等待消息處理完成 msg->wait(); } return res; }
當建立layer的消息被處理時,就會回調上述MessageCreateLayer類中的handler方法。handler方法中調用flinger.createLayer(),第一次還會執行Layer.onFirstRef()
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) { //ALOGD("createLayer for (%d x %d), name=%s", w, h, name.string()); if (int32_t(w|h) < 0) { ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)", int(w), int(h)); return BAD_VALUE; } status_t result = NO_ERROR; sp<Layer> layer; switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceNormal: result = createNormalLayer(client, name, w, h, flags, format, handle, gbp, &layer); break; case ISurfaceComposerClient::eFXSurfaceDim: result = createDimLayer(client, name, w, h, flags, handle, gbp, &layer); break; default: result = BAD_VALUE; break; } if (result != NO_ERROR) { return result; } result = addClientLayer(client, *handle, *gbp, layer); if (result != NO_ERROR) { return result; } setTransactionFlags(eTransactionNeeded); return result; }
在執行Layer::onFirstRef()會新建一個緩衝區隊列的消費者與客戶端APP的生產者對應:
void Layer::onFirstRef() { //surfaceflinger中新建一個緩衝區隊列的消費者 mBufferQueue = new SurfaceTextureLayer(mFlinger); mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mBufferQueue, mTextureName); mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mSurfaceFlingerConsumer->setFrameAvailableListener(this); mSurfaceFlingerConsumer->setName(mName); #ifdef TARGET_DISABLE_TRIPLE_BUFFERING #warning "disabling triple buffering" mSurfaceFlingerConsumer->setDefaultMaxBufferCount(2); #else mSurfaceFlingerConsumer->setDefaultMaxBufferCount(3); #endif const sp<const DisplayDevice> hw(mFlinger->getDefaultDisplayDevice()); updateTransformHint(hw); }
(1)FrameBuffer(幀緩衝,存儲圖形、圖像的緩衝):
Frame:幀,就是指一幅圖像。在屏幕a上看到的一幅圖像就是一幀。
Buffer:緩衝,就是一段存儲區域(存儲的是幀) 。
(2) PageFlipping(畫面交換),用於圖像、圖形數據的生產和消費
操做過程:
一、分配一個能容納兩幀數據的緩衝Buffer,前面一個緩衝叫FrontBuffer,後一個叫BackBuffer;
二、消費者使用FontBuffer中的舊數據,而生產者使用新數據填充BackBuffer,兩者互不干擾;
三、當須要更新顯示時,BackBuffer變成oFrontBuffer,FrontBuffer變成BackBuffer。如此循環。