本篇針對Surface模塊進行分析,從Java層的Activity創建開始,到ViewRoot、WindowsManagerService,再到JNI層和Native層。 首先推薦一個Android源碼查看的網站:http://androidxref.com/ Surface的創建涉及三個部分: A ...
本篇針對Surface模塊進行分析,從Java層的Activity創建開始,到ViewRoot、WindowsManagerService,再到JNI層和Native層。
首先推薦一個Android源碼查看的網站:http://androidxref.com/
Surface的創建涉及三個部分:
-
App 進程
App需要將自己的內容顯示在屏幕上,所以App負責發起Surface創建請求,創建好Surface後, 就可以直接可以在canvas上畫圖等,最終都會保存到Surface里的buffer里,最後由SurfaceFlinger合成並顯示。 -
System_Server進程
主要是其中的WindowManagerService, 負責接收APP請求,向SurfaceFlinger發起具體的請求創建Surface, 且WMS需要創建Surface的輔助管理類,如SurfaceControl。 -
SurfaceFlinger
為App進程創建具體的Surface, 在SurfaceFlinger里對應成Layer, 然後負責管理、合成顯示。
總體流程(參考《深入理解Android》,源碼較舊):
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的關係:
Surface像是UI的畫布,APP就像是在Surface上作畫,通過i使用Skia繪製二維圖像,或是用OpenGL繪製三維圖像,最終APP和Surfacea都要進行交互。
SUrface和SurfaceFlinger(SF)的關係:
surface向SF提供數據,SF進行混合數據。
Activity的顯示(Java層)
1、應用程式的顯示和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的作用如下:
- 根據類名以java反射機制的方法創建一個Activity
- 調用Activity的onCreate函數,開始Activity 的生命周期
(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 }
2、 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的作用:
- ViewRoot繼承Handler類,能夠處理消息,重寫了handleMessage函數
- ViewRoot有一個成員變數mSurface,是Surface類型
- ViewRoot有一個W類型的mWinow和一個View類型的mView變數(W是ViewRoot定義的e靜態內部類 static class W extends IWindow.Stub,將參與和Binder的通信)
View、DectorView是UI單元,繪畫工作在OnDraw函數中完成。如果onDraw是畫圖過程,那麼畫布就是Surface。
Surface:有一塊Raw Buffer,Surface操作這塊Raw Buffer,Screen Compositor(即SurfaceFlinger)管理這塊Raw Buffer。
結論:
- ViewRoot的成員變數mSurface(aSurfce類型),他和一塊Raw Buffer有關聯
- ViewRoot是一個ViewParent,他的子View的繪畫操作,是在畫布Surface上展開的
- Surface和SurfaceFlinger交互
在①的setView中,調用的時ViewRoot.java的setView函數:
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { ... ... res = sWindowSession.add(mWindow, mWindowAttributes, getHostVisibility(), mAttachInfo.mContentInsets, mInputChannel); ... }
實現了:
- 保存傳入的View(即DectorView,從ActivityThread層層傳入)
- 調用requestLayout(往handler中發送一個消息,因為ViewRoot是從handlera派生的,所以這個消息最後會由ViewRoot自己處理)
- 調用IWindowSession的add函數(一個跨進程的Binder通信,第一個參數是mWindow,他是W類型,由IWindow.stub派生)
3、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
總結:
1、大致涉及的方法、類的大體流程(回車表示前一方法內調用):
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
2、要點:
(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函數中完成;
Surface(Java層)
通過上面一節的分析可知:
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進行跨進程調用通信的。
Surface(JNI層)
1、在JNI層,首先被調用的時Surface的無參構造函數,代碼:
// Surface.java Public Surface() { ... mCanvas = new CompatibleCanvas(); // CompatibleCanvaso從Canvas類派生 }
Canvas:
畫圖需要:
- Bitmap,用於存儲像素(即畫布,可以當作是一塊數據存儲區域);
- Canvas,用於記載畫圖的動作(例如畫一個矩形),Canvas提供了這些基本操作的繪圖函數;
- Drawing primitive:繪圖基本元素,例如矩形、圓等;
- Paint:用來描述h繪畫時使用的顏色、虛實線等;
一般情況下,Canvas會封裝一塊Bitmap。
2、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()); }
3、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); }
4、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); } }
5、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函數。
調用流程總結:
總結:
1、一個Activity一般都會對應到一個Window, 對應了一個DecorView, ViewRoot
2、ViewRoot中有一個Surface, 就是App可以用於繪製UI的Surface了,在Native層也對應了一個Surface, 在SurfaceFlinger對應的是一個Layer,通過Layer中的Producer可以真正的申請Buffer用於繪製。App中通過Surface中的Canvas的類似lockcanvas介面觸發dequeue buffer流程。
3、 一個ViewRoot在WMS端對應了一個WindowState, WindowState又通過一系列引用關聯到一個SurfaceControl, Native層也有一個SurfaceControl。這個可以用於控制視窗的一些屬性。
4、 WMS native層的SurfaceComposerClient與SurfaceFlinger之間通過ISurfaceComposerClient建立聯繫。一個App在SurfaceFlinger端對應了一個Client,用於處理該App layer的創建等請求。
5、當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
創建Surface的整體流程:
1.1 viewrootImpl.java
在應用啟動時,會通過WindowManagerGlobal去添加view,添加view時會去創建viewRootImpl,然後進行設置view。
viewRootImpl.setView() —> requestLayout()申請佈局—>scheduleTraversals()—>doTraversal()–>performTraversals()
利用IWindowSession和Session通信,調用relayout,註意,這裡mSurface是ViewRootImpl的成員變數,開始調用了無參的構造函數,IWindowSession.aidl文件中,參數mSurface是被out修飾,用來接受在server端創建Surface,然後再binder返回給ViewRootImpl。
1.2 Session.java
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; }
1.3 WindowManagerService.java
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(); } }
1.4 WindowStateAnimator.java
首先創建一個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); }
1.5 android_view_SurfaceControl.cpp
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()); }
1.6 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; 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; }
1.7 Client.cpp
通過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; }
1.8 Layer.cpp
當創建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); }
Surface(Native層)
(1)FrameBuffer(幀緩衝,存儲圖形、圖像的緩衝):
Frame:幀,就是指一幅圖像。在屏幕a上看到的一幅圖像就是一幀。
Buffer:緩衝,就是一段存儲區域(存儲的是幀) 。
(2) PageFlipping(畫面交換),用於圖像、圖形數據的生產和消費
操作過程:
1、分配一個能容納兩幀數據的緩衝Buffer,前面一個緩衝叫FrontBuffer,後一個叫BackBuffer;
2、消費者使用FontBuffer中的舊數據,而生產者使用新數據填充BackBuffer,二者互不幹擾;
3、當需要更新顯示時,BackBuffer變成oFrontBuffer,FrontBuffer變成BackBuffer。如此迴圈。