「Android」 Surface分析

 本篇針對Surface模塊進行分析,從Java層的Activity建立開始,到ViewRoot、WindowsManagerService,再到JNI層和Native層。java

首先推薦一個Android源碼查看的網站:http://androidxref.com/android

Surface的建立涉及三個部分:canvas

  1. App 進程
    App須要將本身的內容顯示在屏幕上,因此App負責發起Surface建立請求,建立好Surface後, 就能夠直接能夠在canvas上畫圖等,最終都會保存到Surface裏的buffer裏,最後由SurfaceFlinger合成並顯示。數組

  2. System_Server進程
    主要是其中的WindowManagerService, 負責接收APP請求,向SurfaceFlinger發起具體的請求建立Surface, 且WMS須要建立Surface的輔助管理類,如SurfaceControl。session

  3. 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進行混合數據。

Activity的顯示(Java層)


 一、應用程序的顯示和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

 


 

  二、 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派生)

 


 

三、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函數中完成;


 

 

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層)


 

一、在JNI層,首先被調用的時Surface的無參構造函數,代碼:

// Surface.java
Public Surface() {
 ...
mCanvas = new CompatibleCanvas();  //   CompatibleCanvaso從Canvas類派生
}

 

 Canvas:

  畫圖須要:

  • Bitmap,用於存儲像素(即畫布,能夠看成是一塊數據存儲區域);
  • Canvas,用於記載畫圖的動做(例如畫一個矩形),Canvas提供了這些基本操做的繪圖函數;
  • Drawing primitive:繪圖基本元素,例如矩形、圓等;
  • Paint:用來描述h繪畫時使用的顏色、虛實線等;

通常狀況下,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

 

建立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(畫面交換),用於圖像、圖形數據的生產和消費

  操做過程:

    一、分配一個能容納兩幀數據的緩衝Buffer,前面一個緩衝叫FrontBuffer,後一個叫BackBuffer;

    二、消費者使用FontBuffer中的舊數據,而生產者使用新數據填充BackBuffer,兩者互不干擾;

    三、當須要更新顯示時,BackBuffer變成oFrontBuffer,FrontBuffer變成BackBuffer。如此循環。

相關文章
相關標籤/搜索