Surface研究報告

Surface研究報告

這篇文章主要描述從 Surface的創建,即客戶數據是如何通過 Surface進行顯示的。

. Activity的創建說起

1.進程的創建

創建 Activity的過程,首先要從創建Activity所在的進程說起。在用戶請求啓動某個應用程序的時候,會調用 ActivityManagerService.startProcessLocked

ActivityManagerService.startProcessLocked

---->newProcessRecordLocked// 創建新的 ProcessRecord,每個經過ActivityManagerService 啓動的進程都有一個 ProcessRecord,其中存儲了進程相關的一切信息,所有這些 ProcessRecord都存儲在AMS 中。

---->Process.start// SystemServer發起請求創建新的進程,並運行 ActivityThread.main

---->AMS.mPidsSelfLocked 中添加新創建的 ProcessRecord,該變量負責管理ProcessRecord

ActivityThread.main

----->ActivityThread.attach

        ----->IActivityManager mgr = ActivityManagerNative.getDefault();
        ----->mgr.attachApplication(mAppThread);// 注意,這裏向服務端發起了一次請求                      
                          ------>ActivityManagerService.attachApplicationLocked(IApplicationThread thread, int pid)
                                    ----->ActivityThread.realStartActivityLocked
                                        ----->ActivityThread.scheduleLaunchActivity                                                                                                             
                                                                                      ----->queueOrSendMessage(H.LAUNCH_ACTIVITY, r);//這裏只是向消息隊列中加入了 LAUNCH_ACTIVITY的消息                                                                         

                                          ---->ActivityThread.handleLaunchActivity

從上述調用過程,我們可以看到所謂 ActivityThread.attach的過程,就是向它綁定的消息隊列中添加消息的過程,但是這個添加的過程是通過服務端 ActivityManagerService完成的。ActivityThread 中有一個 ApplicationThread實例,這個類的定義如下:

private class ApplicationThread extends ApplicationThreadNative

其中 ApplicationThreadNative的定義如下:

public abstract class ApplicationThreadNative extends Binder implements IApplicationThread

由此可見, ApplicationThread是一個服務端,mgr.attachApplication(mAppThread);把它作爲參數發送給ActivityManagerService ActivityManagerService把它存儲在ProcessRecord thread中,最後通過它向 ActivityThread的消息隊列中添加消息來啓動和 shedule ActivityApplicationThread 起到了回調的作用。

特別說明的是 ActivityManagerService是在創建進程得到pid並把 ProcessRecord加入到mPidsSelfLocked 中之後,再在新創建的進程中運行 ActivityThread.main

2.創建Activity

ActivityThread在收到LAUNCH_ACTIVITY 消息後,調用 handleLaunchActivity處理

frameworks/base/core/java/android/app/ActivityThread.java

handleLaunchActivity

----->performLaunchActivity

   ------>activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);

                    ----->activity.attach(appContext, this, getInstrumentation(), r.token,

                        r.ident, app, r.intent, r.activityInfo, title, r.parent,

                        r.embeddedID, r.lastNonConfigurationInstances, config);

                       ----->mWindow=PolicyManager.makeNewWindow(this);//mWindow Window類實例

                                            ----->com.android.internal.policy.impl.Policy.makeNewWindow

                                                                      ------>return new PhoneWindow(context);//PhoneWindow繼承自 Window

                       ----->mWindow.setWindowManager(null, mToken, mComponent.flattenToString()...

                                                           ----->Window.setWindowManager

                                                                                ----->wm = WindowManagerImpl.getDefault();

                                                                                ----->mWindowManager = new LocalWindowManager(wm, hardwareAccelerated);

 

----->handleResumeActivity

                r.window = r.activity.getWindow(); 這裏get得到的 Window就是在activity.attach 中創建的 mWindow,即PhoneWindow

                View decor = r.window.getDecorView();//window.getDecorView 接口的實現實際就是 PhoneWindow.getDecorView

 

frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java

PhoneWindow.getDecorView

                   ----->PhoneWindow.installDecor

                          ----->mDecor = generateDecor();

                                          ----->return new DecorView(getContext(), -1);

                          ----->mContentParent = generateLayout(mDecor);

                                                                ----->View in = mLayoutInflater.inflate(layoutResource, null);

                                                                                 decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));

                                                                                 ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);

    這一句比較奇怪,憑空從哪裏冒出來一個 ID_ANDROID_CONTENT,這就需要看layoutResource變量了,它一定是 layoutResource中定義的某個id,該值在不同情況下,有不同的賦值,它表示一個 layout,這些文件都定義在frameworks/base/core/res/res/layout/目錄,他們有一個共同點就是,都有一個 FrameLayout,且android.id 屬性都是 "@android.id/content"。這裏的findViewById 顯然是查找這個的,也就是說它返回的是一個 FrameLayout,也就是一個ViewGroup

                decor.setVisibility(View.INVISIBLE);

                ViewManager wm = a.getWindowManager();// 從上面attach的過程就可以看到這裏的 WindowManager就是LocalWindowManager

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

                           ----->ViewRootImpl.setView// 每個ViewRootImpl對象中只有一個 View對象

                }

這裏的 wm就是 LocalWindowManager 類的實例,從下面的類圖結構中,我們知道它繼承自 WindowManagerImpl.CompatModeWrapper 類,它的addView 的實現就是調用 WindowManagerImpl.addView WindowManagerImpl 類中包含有一組 View 對象,一組ViewRootImpl 對象,每個 View ViewRootImpl 都是一一對應的。

3.WindowWindowManager ViewRootImpl

下面總結一下上述過程中類之間的關係,他們的類關係圖如下:


 

首先, Activity中有一個PhoneWindow ,它從Window抽象類繼承而來,它持有一個 DecorView,這裏就要說道Window View之間的關係,Window類的註釋如下:

 * Abstract base class for a top-level window look and behavior policy.  An

 * instance of this class should be used as the top-level view added to the

 * window manager. It provides standard UI policies such as a background, title

 * area, default key processing, etc.

 * The only existing implementation of this abstract class is

 * android.policy.PhoneWindow, which you should instantiate when needing a

 * Window.  Eventually that class will be refactored and a factory method

 * added for creating Window instances without knowing about a particular

 * implementation.

Window是一個抽象類,它應該作爲 top-level view添加到Window Manager 中,PhoneWindow是它的唯一實現, PhoneWindow持有一個DecorView 實例,它是這個 Windowtop-level view ,它定義在 frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java ,從類圖中我們知道它是一個 FrameLayout,所以可以包含其他view FrameLayout繼承自ViewGroup ViewGroup繼承自 View,並實現了ViewManager ViewParent接口,這兩個接口是有區別的, ViewManager提供了addView,removeView 的接口,用於管理 ViewViewParent 則用於和 parent打交道,例如向parent發送某種請求,如 requestLayout

View當然是所有顯示單元的基類。

 

Surface的創建

1.IWindowSession的創建

Window類還有一個WindowManager 的引用, WindowManager類註釋中說明context.getSystemService(Context.WINDOW_SERVICE)得到的就是一個WindowManager,它與 WindowService服務通信,但是WindowManager並沒有從 Binder繼承,這是怎麼回事呢,原來, WindowManager的派生類WindowManagerImpl.CompatModeWrapper 中有一個 Display類,Display 中有一個 IWindowManager引用,顯然這纔是真正與 Window service通信的類。

WindowManagerImpl在進程中只有一個實例,在 WindowManagerImpl類中,包含有一組ViewRootImpl View的映射,ViewRootImpl.setView 方法中使用了 sWindowSession.add方法,其中sWindowSession 是一個static IWindowSession,由於它是 static的,所以在進程中它也只有一個實例。顯然這個類是用於與服務器端通信的,它是與誰通信,它的功能如何呢?

ViewRootImpl的構造函數中調用了 getWindowSession函數,ViewRootImpl.getWindowSession 定義如下:

public static IWindowSession getWindowSession(Looper mainLooper) {

        synchronized (mStaticInit) {

            if (!mInitialized) {

                try {

                    InputMethodManager imm = InputMethodManager.getInstance(mainLooper);

                    sWindowSession = Display.getWindowManager().openSession(

                            imm.getClient(), imm.getInputContext());

                    mInitialized = true;

                } catch (RemoteException e) {

                }

            }

            return sWindowSession;

        }

    }

其中的 sWindowSessionIWindowSession 類型,這裏顯然是創建 sWindowSession的地方,Display.getWindowManager 的定義如下:

static IWindowManager getWindowManager() {

        synchronized (sStaticInit) {

            if (sWindowManager == null) {

                sWindowManager = IWindowManager.Stub.asInterface(

                        ServiceManager.getService("window"));

            }

            return sWindowManager;

        }

    }

這裏的 sWindowManagerIWindowManager 類型,IWindowManager.openSession定義如下:

public android.view.IWindowSession openSession(com.android.internal.view.IInputMethodClient client, com.android.internal.view.IInputContext inputContext) throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

android.view.IWindowSession _result;

try {

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeStrongBinder((((client!=null))?(client.asBinder()):(null)));

_data.writeStrongBinder((((inputContext!=null))?(inputContext.asBinder()):(null)));

mRemote.transact(Stub.TRANSACTION_openSession, _data, _reply, 0);// 這裏顯然是發送請求,並得到 reply響應。

_reply.readException();

_result = android.view.IWindowSession.Stub.asInterface(_reply.readStrongBinder());// 這裏得到 IWindowSessionBpBinder ,通過asInterface得到 BpProxy

}

finally {

_reply.recycle();

_data.recycle();

}

return _result;

}

我們再來看在同一個文件中的服務器端的代碼

case TRANSACTION_openSession:

{

data.enforceInterface(DESCRIPTOR);

com.android.internal.view.IInputMethodClient _arg0;

_arg0 = com.android.internal.view.IInputMethodClient.Stub.asInterface(data.readStrongBinder());

com.android.internal.view.IInputContext _arg1;

_arg1 = com.android.internal.view.IInputContext.Stub.asInterface(data.readStrongBinder());

android.view.IWindowSession _result = this.openSession(_arg0, _arg1);// 調用服務端的 openSession得到IWindowSession

reply.writeNoException();

reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));

return true;

}

顯然 this.openSession(_arg0, _arg1);是我們要找的代碼,這裏的 this就是WindowManagerService 類,因爲它是從 IWindowManager.Stub繼承的,在該類中

public IWindowSession openSession(IInputMethodClient client,

            IInputContext inputContext) {

        if (client == null) throw new IllegalArgumentException("null client");

        if (inputContext == null) throw new IllegalArgumentException("null inputContext");

        Session session = new Session(this, client, inputContext);

        return session;

    }

該函數返回了一個 Session,該類定義在frameworks/base/services/java/com/android/server/wm/Session.java,它繼承自IWindowSession.Stub ,也就是說它是一個服務器端,當然通過 Binder之後,在客戶端得到的是一個客戶端 BinderSession 中包含有 WindowManagerService的引用,這樣,在客戶端發起請求,在服務器端收到後,可以通過該引用調用 WindowManagerService的方法。

這樣, ViewRootImpl.getWIndowSession就得到了一個進程唯一的 IWindowSession實例。

 

2.ViewRootImpl.setView

讓我們從 ViewRootImpl.setView重新看起,它調用了sWindowSession.add 方法,即調用到服務端的 add代碼,Session.add 代碼如下

public int add(IWindow window, int seq, WindowManager.LayoutParams attrs,

            int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {

        return mService.addWindow(this, window, seq, attrs, viewVisibility, outContentInsets,

                outInputChannel);

    }

也即調用了 WindowManagerService.addWindow方法,在該方法中,

win = new WindowState(this, session, client, token,

                    attachedWindow, seq, attrs, viewVisibility);

。。。

win.attach();

     ----->mSession.windowAddedLocked();

                      ----->mSurfaceSession = new SurfaceSession();

                      ----->mService.mSessions.add(this);

。。。

mWindowMap.put(client.asBinder(), win);

WindowStatewindow manager 管理的window對象。它其中包含了 WindowManagerService引用,Session 引用,IWindow引用。 WindowManagerService引用顯然是爲了調用它提供的方法的, Session引用是爲了表示進程的,因爲它是進程唯一的,那麼 IWindow引用的作用是什麼呢?

我們從 ViewRootImpl.setView看起,它調用res = sWindowSession.add(mWindow, mSeq, mWindowAttributes,。。。)。這裏的 mWindow的類型是W ,它在ViewRootImpl的構造函數中初始化

        mWindow = new W(this);

W繼承自IWindow.Stub IWindow.Stub IWindow.java中定義,它顯然是個服務器端類,這樣 IWindow的作用就很明顯了,在addWindow的時候,它被添加到 WindowManagerServiceWindowState 中,當然,在 binder傳遞的過程中,它變成了一個客戶端類,在 WindowManagerService需要通知客戶端程序發生某種事件的時候,就會調用 IWindow的接口,在這裏有resized dispatchAppVisibilitydispatchGetNewSurface windowFocusChanged,顯然這種方法是 AndroidService 中經常採用的策略。 IWindow.Stub接口在每個ViewRootImpl 實例中,只有一個實例,它與 ViewRootImplView 都是一一對應的。也就是說 WindowState通過它就唯一標識了一個窗口。每個客戶端進程對應一個 Session實例

在創建了 WindowState之後,調用了它的attach函數,其中調用了 Session.windowAddedLocked方法,它實際上就是創建了一個 SurfaceSession實例。這個實例後面創建 Surface的時候會用到,現在只要知道,它是 Session持有的,並且是一對一的關係,即一個客戶進程是對應一個 SurfaceSession的。

 

3.Surface的傳遞

ViewRootImpl.setView

----->requestLayout

  ----->scheduleTraversals

           ----->sendEmptyMessage(DO_TRAVERSAL);

                   ----->handleMessage()// 這裏需要特別說以下,因爲 ViewRootImpl是從Handler 派生的,所以在創建的時候,就與當前線程的 Looper綁定了,在投放消息後,會調用 HandlerhandleMessage 進行處理

                                ---->performTraversals

                                           ----->relayoutWindow

                                                          ----->sWindowSession.relayout(mWindow, mSeq, params, (int) (mView.getMeasuredWidth() * appScale + 0.5f), (int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility, insetsPending, mWinFrame, mPendingContentInsets, mPendingVisibleInsets, mPendingConfiguration, mSurface);

這裏的 sWindowSession.relayout實際上就是發起一次請求,需要特別注意兩個參數,一個是第一個參數 mWindow,它是IWindow.Stub 類型,在服務器端收到這個請求後,就是根據這個參數來查找 WindowState對象的,另外一個參數,是最後一個參數 mSurface,它是Surface 類型,它在 JNI層會被綁定從服務器端傳遞的 SurfaceControl對象。

IWindowSession中,我們可以看到這個客戶端的請求,在服務器端的響應就是調用 Session.relayout

Session.relayout

----->WindowManagerService.relayoutWindow

                  ----->Surface surface = win.createSurfaceLocked();// 該函數會在 WindowState對象中創建一個Surface對象

                                           ----->mSurface = new Surface( mSession.mSurfaceSession, mSession.mPid, mAttrs.getTitle().toString(), 0, w, h, format, flags);

                                  ----->outSurface.copyFrom(surface);

看到這裏就涉及 Surface對象在進程間的傳遞了,在客戶端這一側, sWindowSession.relayout中的參數ViewRootImpl.mSurface 是在定義的時候就初始化了的

    private final Surface mSurface = new Surface();

因爲 sWindowSessionIWindowSession 類型,我們接着看它對應的 relayout函數

out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/view/IWindowSession.java

public int relayout(android.view.IWindow window, int seq, android.view.WindowManager.LayoutParams attrs, int requestedWidth, int requestedHeight, int viewVisibility, boolean insetsPending, android.graphics.Rect outFrame, android.graphics.Rect outContentInsets, android.graphics.Rect outVisibleInsets, android.content.res.Configuration outConfig, android.view.Surface outSurface) throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

int _result;

try {

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeStrongBinder((((window!=null))?(window.asBinder()):(null)));

_data.writeInt(seq);

if ((attrs!=null)) {

_data.writeInt(1);

attrs.writeToParcel(_data, 0);

}

else {

_data.writeInt(0);

}

_data.writeInt(requestedWidth);

_data.writeInt(requestedHeight);

_data.writeInt(viewVisibility);

_data.writeInt(((insetsPending)?(1):(0)));

mRemote.transact(Stub.TRANSACTION_relayout, _data, _reply, 0);//客戶端發起relayout請求,並返回reply

_reply.readException();

_result = _reply.readInt();

if ((0!=_reply.readInt())) {

outFrame.readFromParcel(_reply);

}

if ((0!=_reply.readInt())) {

outContentInsets.readFromParcel(_reply);

}

if ((0!=_reply.readInt())) {

outVisibleInsets.readFromParcel(_reply);

}

if ((0!=_reply.readInt())) {

outConfig.readFromParcel(_reply);

}

if ((0!=_reply.readInt())) {

outSurface.readFromParcel(_reply);//reply中讀取outSurface

}

}

finally {

_reply.recycle();

_data.recycle();

}

return _result;

我們需要特別注意 mRemote.transact(Stub.TRANSACTION_relayout, _data, _reply, 0); 調用後返回的 _replyoutSurface.readFromParcel(_reply); 其中outSurface就是傳遞的最後一個參數,即 ViewRootImpl.mSurface

在服務器端的 relayout過程中,也會創建Surface對象,它使用的是Surface的另外一個構造函數,它會調用 native函數init ,對應Surface_init函數

frameworks/base/core/jni/android_view_Surface.cpp

static void Surface_init(

        JNIEnv* env, jobject clazz,

        jobject session,

        jint, jstring jname, jint dpy, jint w, jint h, jint format, jint flags)

            (SurfaceComposerClient*)env->GetIntField(session, sso.client);

----->    SurfaceComposerClient* client =

            (SurfaceComposerClient*)env->GetIntField(session, sso.client);

----->sp surface;

----->surface = client->createSurface(dpy, w, h, format, flags);

                                    ----->sp surface = mClient->createSurface(&data, name,display, w, h, format, flags);//

                                    ----->result = new SurfaceControl(this, surface, data);

----->setSurfaceControl(env, clazz, surface);

這裏的參數 session對應着mSurface.mSurfaceSession 對象,在前面的分析中, WindowState.attach的時候創建了SurfaceSession對象,它也是進程唯一的,實際上它的構造函數中調用了 native函數init ,對應SurfaceSession_init函數,該函數也定義在 android_view_Surface.cpp

static void SurfaceSession_init(JNIEnv* env, jobject clazz)

{

    sp client = new SurfaceComposerClient;

    client->incStrong(clazz);

    env->SetIntField(clazz, sso.client, (int)client.get());

}

這裏創建了一個 SurfaceComposerClient對象,並把這個對象與SurfaceSession對象綁定。在 Surface_init函數中,從SurfaceSession java 對象上獲取的就是這個 client,SurfaceSession對象的職責就是把Session與Surface關聯起來。這個client創建一個 surfacecontrol,並把它與Surface java 對象綁定 ,而這一切的動作都是在WindowManagerService所在進程進行的。所謂的 Surface.copyFrom實際上傳遞的就是與Surface對象綁定的 SurfaceControl native對象,在進程間傳遞的也是 SurfaceControl對象。

SurfaceControl native 對象中包含的最重要的就是 ISurface native實例,它被傳遞到客戶端進程後,與 ViewRootImpl.mSurface java對象綁定,該對象是一個 Surface類型。

 

4.ISurface的創建

現在來看最重要的創建ISurface的過程,在上面的代碼中 SurfaceComposerClient創建了ISurface 實例

mClientSurfaceComposerClient 對象的成員變量,它是 sp類型的,它是在如下的代碼中初始化的,也就是在 SurfaceComposerClient對象第一次被引用的時候

void SurfaceComposerClient::onFirstRef() {

    sp sm(getComposerService());

    if (sm != 0) {

        sp conn = sm->createConnection();

        if (conn != 0) {

            mClient = conn;

            mStatus = NO_ERROR;

        }

    }

}

其中 getComposerService()定義如下:

static inline sp getComposerService() {

    return ComposerService::getComposerService();

}

sp ComposerService::getComposerService() {

    return ComposerService::getInstance().mComposerService;

}

ComposerService的類定義如下:

class ComposerService : public Singleton

{

    // these are constants

    sp mComposerService;

    sp mServerCblkMemory;

    surface_flinger_cblk_t volatile* mServerCblk;

    ComposerService();

    friend class Singleton;

public:

    static sp getComposerService();

    static surface_flinger_cblk_t const volatile * getControlBlock();

};

它是一個單件,從 Singleton模板繼承而來,只有一個實例,它的構造函數如下:

ComposerService::ComposerService()

: Singleton() {

    const String16 name("SurfaceFlinger");

    while (getService(name, &mComposerService) != NO_ERROR) {

        usleep(250000);

    }

    mServerCblkMemory = mComposerService->getCblk();

    mServerCblk = static_cast(

            mServerCblkMemory->getBase());

}

其中 getService(name, &mComposerService)函數是定義在IServiceManager.h中的函數,功能是根據名稱獲取 Servcie的客戶端,顯然,這裏是根據 SurfaceFlinger名稱得到了該服務的客戶端,其接口類型是 ISurfaceComposer,也就是說,上述createConnection函數,是客戶端向服務器端發起的請求,顯然返回的類型是一個 ISurfaceComposerClient類型,那麼服務器端是如何處理的呢?首先,我們就要找到這個 Service

init.rc中,啓動了 surfaceflinger服務,

service surfaceflinger /system/bin/surfaceflinger

這個可執行文件是在 frameworks/base/cmds/surfaceflinger/main_surfaceflinger.cpp 編譯出來的,該文件的內容非常簡單,如下所示:

int main(int argc, char** argv) {

    SurfaceFlinger::publishAndJoinThreadPool();

    return 0;

}

我們來看 SurfaceFlinger類的定義

frameworks/base/services/surfaceflinger/SurfaceFlinger.h

class SurfaceFlinger :

        public BinderService,

        public BnSurfaceComposer,

        public IBinder::DeathRecipient,

        protected Thread

在它的基類 BinderService類中,定義了publishAndJoinThreadPool函數,它是一個模板類,該函數定義如下:

static void publishAndJoinThreadPool() {

        sp proc(ProcessState::self());

        sp sm(defaultServiceManager());

        sm->addService(String16(SERVICE::getServiceName()), new SERVICE());

        ProcessState::self()->startThreadPool();

        IPCThreadState::self()->joinThreadPool();

    }

這與我們在前面分析 Binder的時候,添加服務的過程是相同的,同時,我們看到 SurfaceFlinger類也從是BnSurfaceComposer 繼承的, BnSurfaceComposer是在frameworks/base/include/surfaceflinger/ISurfaceComposer.h 定義的,它從 BnInterface繼承而來,也就是說SurfaceFlinger就是我們要找的服務器端類,

sp SurfaceFlinger::createConnection()

{

    sp bclient;

    sp client(new Client(this));

    status_t err = client->initCheck();

    if (err == NO_ERROR) {

        bclient = client;

    }

    return bclient;

}

這樣 SurfaceComposerClient在收到這個返回的ISurfaceComposerClient實例之後,將一直持有它。由於 SurfaceComposerClient實例與SurfaceSession 是一一對應的, ISurfaceComposerClientSurfaceComposerClient 也是一一對應的,而 SurfaceSession是進程唯一的,所以SurfaceComposerClient實例,與 ISurfaceComposerClient實例也是進程唯一的,上述過程可用如下圖表示


在上述代碼中 Client的類型定義如下:

class Client : public BnSurfaceComposerClient ,也就是說,它也是一個服務器端類,它的 createSurface函數如下:

sp Client::createSurface(

        ISurfaceComposerClient::surface_data_t* params,

        const String8& name,

        DisplayID display, uint32_t w, uint32_t h, PixelFormat format,

        uint32_t flags)

{

    /*

     * createSurface must be called from the GL thread so that it can

     * have access to the GL context.

     */

 

    class MessageCreateSurface : public MessageBase {

        sp result;

        SurfaceFlinger* flinger;

        ISurfaceComposerClient::surface_data_t* params;

        Client* client;

        const String8& name;

        DisplayID display;

        uint32_t w, h;

        PixelFormat format;

        uint32_t flags;

    public:

        MessageCreateSurface(SurfaceFlinger* flinger,

                ISurfaceComposerClient::surface_data_t* params,

                const String8& name, Client* client,

                DisplayID display, uint32_t w, uint32_t h, PixelFormat format,

                uint32_t flags)

            : flinger(flinger), params(params), client(client), name(name),

              display(display), w(w), h(h), format(format), flags(flags)

        {

        }

        sp getResult() const { return result; }

        virtual bool handler() {

            result = flinger->createSurface(params, name, client,

                    display, w, h, format, flags);

            return true;

        }

    };

 

    sp msg = new MessageCreateSurface(mFlinger.get(),

            params, name, this, display, w, h, format, flags);

    mFlinger->postMessageSync(msg);

    return static_cast( msg.get() )->getResult();

}

顯然,上面的代碼是創建一個消息,然後把它投放到一個消息隊列中,其中關鍵的是 mFlinger->postMessageSync(msg),其代碼如下:

status_t SurfaceFlinger::postMessageSync(const sp& msg,

        nsecs_t reltime, uint32_t flags)

{

    status_t res = mEventQueue.postMessage(msg, reltime, flags);

    if (res == NO_ERROR) {

        msg->wait();

    }

    return res;

}

也就是說, msg消息會被放入到EventQueue消息隊列中,進行處理, msg->wait表示等待消息處理完成,這就說明問題了, postMessage所在的線程,與消息處理的線程必然是兩個線程,那麼這些線程又是如何創建的呢?

從前面創建 SurfaceFlinger服務的時候,我們知道SufaceFlinger的類繼承結構, SurfaceFlinger繼承自Thread ,看下面的代碼

void SurfaceFlinger::onFirstRef()

{

    run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);

 

    // Wait for the main thread to be done with its initialization

    mReadyToRunBarrier.wait();

}

我們從這裏可以看到,它調用了 Thread.run函數,該函數會啓動一個新的線程,在線程中將運行 threadLoop函數,mReadyToRunBarrier.wait(); 是爲了等待線程啓動起來,也就是說,在 init進程啓動SurfaceFlinger 服務進程之後,創建 SurfaceFlinger實例,並在該實例第一次得到引用的時候,會啓動一個新的線程,這個線程就是調用的就是 SurfaceFlinger.threadLoop函數,該函數代碼如下:

bool SurfaceFlinger::threadLoop()

{

    waitForEvent();

           ----->while(true)

           ----->sp msg = mEventQueue.waitMessage(timeout);

                                                                                                        ----->msg->handler()

                                                                                                        ----->msg->notify

    。。。

}

注意,我們在 SurfaceFlinger::postMessageSync中,在把消息投入消息隊列之後,調用了 msg->wait,也就是說該函數所在的線程被阻塞了,而上面的函數調用中, msg->notify顯然是用來恢復這個阻塞的,這也就是 postMessageSyncSync 的含義了。而在這裏 handler的內容就是創建Surface

result = flinger->createSurface(params, name, client,display, w, h, format, flags);

該函數返回一個 ISurface的實例,並被保存在msg result變量中,最後返回給客戶端進程,下面我們來看一下整體的創建流程

SurfaceFlinger service 的創建流程如下:

SystemServer進程創建WindowState 的過程如下:

SystemServer創建Surface 的過程如下:

SurfaceFlinger進程使用到的類關係如下:

SystemServer使用到的類關係如下:

ISurfaceComposer接口是SurfaceFlinger 提供的服務接口

ISurfaceComposerClient 是客戶端進程與 SurfaceFlinger進程鏈接的通道,客戶端進程並不直接使用 ISurfaceComposer接口,而是通過ISurfaceComposerClient接口,在服務器端進程調用 SurfaceFlinger實例的服務,由於ISurfaceComposerClient實例是保存在 SurfaceComposerClient中,它與SurfaceSession 是一一對應的,而 SurfaceSessionSession 又是一一對應的, Session在進程中是隻有一個實例的,所以這個 ISurfaceComposerClient在進程中也是隻有一個實例的。

 

SurfaceFlinger::createSurface

----->SurfaceFlinger::createSurface(

----->ssize_t token = addClientLayer(client, layer);

                         ----->size_t name = client->attachLayer(lbc);

                                         ----->Client.mLayers.add(name,layer);

                         ----->addLayer_l(lbc);

                                         ----->ssize_t i = mCurrentState.layersSortedByZ.add(layer);

----->surfaceHandle = layer->getSurface();

                         ----->s = createSurface();

                         ---->mClientSurfaceBinder = s->asBinder();

sp LayerBaseClient::createSurface()

{

    class BSurface : public BnSurface, public LayerCleaner {

        wp mOwner;

        virtual sp getSurfaceTexture() const {

            sp res;

            sp that( mOwner.promote() );

            if (that != NULL) {

                res = that->mSurfaceTexture;

            }

            return res;

        }

    public:

        BSurface(const sp& flinger,

                const sp& layer)

            : LayerCleaner(flinger, layer), mOwner(layer) { }

    };

    sp sur(new BSurface(mFlinger, this));

    return sur;

}

從這裏我們可以看到返回給客戶端進程的 ISurface實例是如何創建的,同時, ISurface接口只有一個功能就是getSurfaceTexture,從這裏也可以看到,它的作用就是返回這個 LayerISurefaceTexture 實例。另外,從上述過程中,我們可以看到在創建了 Surface之後,這個實例被保存在 layerbaseclient中。另外,LayerBaseClient 類本身就有 createSurface函數,如下:

sp LayerBaseClient::createSurface()

{

    class BSurface : public BnSurface, public LayerCleaner {

        virtual sp getSurfaceTexture() const { return 0; }

    public:

        BSurface(const sp& flinger,

                const sp& layer)

            : LayerCleaner(flinger, layer) { }

    };

    sp sur(new BSurface(mFlinger, this));

    return sur;

}

從這裏看到它的 getSufaceTexture方法返回的是0,這是什麼意思呢? LayerBaseClient除了有Layer 這個派生類之外,還有 LayerDimLayerScreenshot 派生類,他們都沒有實現 createSurface方法,而是使用父類的函數,也就是說,只有創建了 Layer,才能得到ISurfaceTexture 接口,如果創建了其他兩種 LayerBaseClient,則得不到這個接口。

上述過程可以用如下圖表示:


 

我們以客戶端進程 add一個View ,重新回顧整個創建過程,一個 View對應一個ViewRootImpl ViewRootImpl中有一個 IWindowSession接口實例,它是進程唯一的,通過它的 add方法,使WindowManagerService使用與這個 Session 綁定的ISurfaceComposerClient 接口向SurfaceFlinger 進程,來創建一個 ISurface接口,這個實例被保存在 SurfaceControl實例中,這個native層的實例與 java層的Surface 實例綁定到一起,並通過 IWindowSession接口傳遞給客戶端進程。也就是說,一個 View對應了一個ISurface 接口,又對應一個 Layer,對應一個SurfaceTexture

 

 

 .Surface的使用

上面我們看到了 ISurface接口是如何創建的,以及它是如何與 Surface java對象綁定到一起的,下面我們將要看到客戶端進程是如何使用 Surface顯示內容的。

我們從 Surface.lockCanvas看起

1.Surface.lockCanvas

Surface.java中的 Surface.lockCanvas知道,它調用了native函數 lockCanvasNative函數,即frameworks/base/core/jni/android_view_Surface.cpp 文件中的 Surface_lockCanvas函數

static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)

{

    const sp& surface(getSurface(env, clazz));

。。。。。。

 

    Surface::SurfaceInfo info;

    status_t err = surface->lock(&info, &dirtyRegion);

。。。。。。

    SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);

    SkBitmap bitmap;

。。。。。。

    if (info.w > 0 && info.h > 0) {

        bitmap.setPixels(info.bits);

    } else {

        // be safe with an empty bitmap.

        bitmap.setPixels(NULL);

    }

    nativeCanvas->setBitmapDevice(bitmap);

。。。。。。

    return canvas;

}

這段代碼的主要功能是使用 surface->lock得到SurfaceInfo ,然後把 info.bits設置給SkBitmap ,這個bitmap最後設置給 nativeCanvas,也就是說,在這個Canvas上畫的數據都會被寫道其中的 bitmap上,也就是info.bits 指定的地址上,這個地址上的數據就是顯示數據。所以這段代碼的關鍵是 Surface->lock函數。

2.Surface::lock

下面我們將從 Surface::lock開始,分析Surface 對象是如何與 SurfaceTexture通信的

frameworks/base/libs/gui/Surface.cpp

status_t Surface::lock(SurfaceInfo* other, Region* inOutDirtyRegion)

------>status_t err = SurfaceTextureClient::lock(&outBuffer, inOutDirtyBounds);

Surface繼承自SurfaceTextureClient ,它直接調用了基類的 lock函數

status_t SurfaceTextureClient::lock(

        ANativeWindow_Buffer* outBuffer, ARect* inOutDirtyBounds)

{

    if (mLockedBuffer != 0) {

        LOGE("Surface::lock failed, already locked");

        return INVALID_OPERATION;

    }

 

    if (!mConnectedToCpu) {

        int err = SurfaceTextureClient::connect(NATIVE_WINDOW_API_CPU);

                           ----->int err = mSurfaceTexture->connect(api,&mDefaultWidth, &mDefaultHeight, &mTransformHint);//---------------

        if (err) {

            return err;

        }

        // we're intending to do software rendering from this point

        setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);

    }

 

    ANativeWindowBuffer* out;

    status_t err = dequeueBuffer(&out);

                         ------>status_t result = mSurfaceTexture->dequeueBuffer(&buf, mReqWidth, mReqHeight,mReqFormat, mReqUsage);--------------

 

    LOGE_IF(err, "dequeueBuffer failed (%s)", strerror(-err));

    if (err == NO_ERROR) {

        sp backBuffer(GraphicBuffer::getSelf(out));

        err = lockBuffer(backBuffer.get());

        LOGE_IF(err, "lockBuffer (handle=%p) failed (%s)",

                backBuffer->handle, strerror(-err));

        if (err == NO_ERROR) {

            const Rect bounds(backBuffer->width, backBuffer->height);

 

            Region newDirtyRegion;

            if (inOutDirtyBounds) {

                newDirtyRegion.set(static_cast(*inOutDirtyBounds));

                newDirtyRegion.andSelf(bounds);

            } else {

                newDirtyRegion.set(bounds);

            }

 

            // figure out if we can copy the frontbuffer back

            const sp& frontBuffer(mPostedBuffer);

            const bool canCopyBack = (frontBuffer != 0 &&

                    backBuffer->width  == frontBuffer->width &&

                    backBuffer->height == frontBuffer->height &&

                    backBuffer->format == frontBuffer->format);

 

            if (canCopyBack) {

                // copy the area that is invalid and not repainted this round

                const Region copyback(mOldDirtyRegion.subtract(newDirtyRegion));

                if (!copyback.isEmpty())

                    copyBlt(backBuffer, frontBuffer, copyback);--------------

            } else {

                // if we can't copy-back anything, modify the user's dirty

                // region to make sure they redraw the whole buffer

                newDirtyRegion.set(bounds);

            }

 

            // keep track of the are of the buffer that is "clean"

            // (ie: that will be redrawn)

            mOldDirtyRegion = newDirtyRegion;

 

            if (inOutDirtyBounds) {

                *inOutDirtyBounds = newDirtyRegion.getBounds();

            }

 

            void* vaddr;

            status_t res = backBuffer->lock(

                    GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN,

                    newDirtyRegion.bounds(), &vaddr);--------------

 

            LOGW_IF(res, "failed locking buffer (handle = %p)",

                    backBuffer->handle);

 

            mLockedBuffer = backBuffer;

            outBuffer->width  = backBuffer->width;

            outBuffer->height = backBuffer->height;

            outBuffer->stride = backBuffer->stride;

            outBuffer->format = backBuffer->format;

            outBuffer->bits   = vaddr;

        }

    }

    return err;

}

下面依次對上面 4個函數進行分析

connect

這裏顯然是客戶端發起請求,其中 api參數是NATIVE_WINDOW_API_CPU ,對應的,在 SurfaceTextureconnect ,實際上就是記錄這個 api,並返回它保存的defaultWidth defaultHeight

dequeueBuffer

同樣的是客戶端發起請求,關鍵是看 SurfaceTexture::dequeueBuffer函數,該函數實際上就是在其成員變量 mSlots數組中查找一個合適的位置,並返回數組的序號,特別需要說明的是,如果這個合適位置的 buffer是經過重新分配得到的話,那麼客戶端還需要調用 requestBuffer方法才能重新得到新的GraphicBuffer

copyBlt

先說明 frontBufferbackBuffer ,這是兩個邏輯概念,上次使用的 buffer被稱爲frontBuffer ,它保存在 mPostedbuffer,而現在將要使用的稱爲 backBuffer,在lock 之後,將使用 mLockedBuffer來保存它。在後面說明的 unlockAndPost函數之中,將把這個buffer變成 frontBuffer,即PostedBuffer 

lock

status_t GraphicBuffer::lock(uint32_t usage, const Rect& rect, void** vaddr)

{

    if (rect.left < 0 || rect.right  > this->width ||

        rect.top  < 0 || rect.bottom > this->height) {

        LOGE("locking pixels (%d,%d,%d,%d) outside of buffer (w=%d, h=%d)",

                rect.left, rect.top, rect.right, rect.bottom,

                this->width, this->height);

        return BAD_VALUE;

    }

    status_t res = getBufferMapper().lock(handle, usage, rect, vaddr);

    return res;

}

getBufferMapper()函數得到的是一個GraphicBufferMapper實例,實際上這個類是個單件,只有一個實例

status_t GraphicBufferMapper::lock(buffer_handle_t handle,

        int usage, const Rect& bounds, void** vaddr)

{

    status_t err;

 

    err = mAllocMod->lock(mAllocMod, handle, usage,

            bounds.left, bounds.top, bounds.width(), bounds.height(),

            vaddr);

 

    LOGW_IF(err, "lock(...) failed %d (%s)", err, strerror(-err));

    return err;

}

其中 mAllocMod是在構造函數中得到的

GraphicBufferMapper::GraphicBufferMapper()

    : mAllocMod(0)

{

    hw_module_t const* module;

    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);

    LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);

    if (err == 0) {

        mAllocMod = (gralloc_module_t const *)module;

    }

}

該函數通過加載 gralloc.so得到hw_module_t ,也就是 gralloc_module_t,其定義如下:

hardware/libhardware/include/hardware/gralloc.h

/**

 * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM

 * and the fields of this data structure must begin with hw_module_t

 * followed by module specific information.

 */

typedef struct gralloc_module_t {

    struct hw_module_t common;

    int (*registerBuffer)(struct gralloc_module_t const* module,

            buffer_handle_t handle);

    int (*unregisterBuffer)(struct gralloc_module_t const* module,

            buffer_handle_t handle);

    int (*lock)(struct gralloc_module_t const* module,

            buffer_handle_t handle, int usage,

            int l, int t, int w, int h,

            void** vaddr);

    int (*unlock)(struct gralloc_module_t const* module,

            buffer_handle_t handle);

    void* reserved_proc[7];

} gralloc_module_t;

這裏我們可以看到上面調用的 lock函數,顯然GraphicBufferMapper 類是對這些方法的封裝,在 GraphicBuffer類中使用了這些函數,那麼這些函數的具體實現如何?他們的功能又是如何呢?這就要看看 gralloc模塊的實現了。

3.Gralloc module

gralloc module涉及兩個文件

hardware/libhardware/modules/gralloc/gralloc.cpp 中定義了服務器端用於分配內存的代碼,

hardware/libhardware/modules/gralloc/mapper.cpp 中定義了客戶端用於註冊的代碼,下面我們分別來看看他們是如何實現的


上圖給出了 moduledevice 相關的結構之間的關係,他們的定義分別如下:

hardware/libhardware/modules/gralloc/gralloc_priv.h

struct private_module_t {

    gralloc_module_t base;

 

    private_handle_t* framebuffer;

    uint32_t flags;

    uint32_t numBuffers;

    uint32_t bufferMask;

    pthread_mutex_t lock;

    buffer_handle_t currentBuffer;

    int pmem_master;

    void* pmem_master_base;

 

    struct fb_var_screeninfo info;

    struct fb_fix_screeninfo finfo;

    float xdpi;

    float ydpi;

    float fps;

};

hardware/libhardware/include/hardware/hardware.h

/**

 * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM

 * and the fields of this data structure must begin with hw_module_t

 * followed by module specific information.

 */

typedef struct hw_module_t {

    /** tag must be initialized to HARDWARE_MODULE_TAG */

    uint32_t tag;

 

    /** major version number for the module */

    uint16_t version_major;

 

    /** minor version number of the module */

    uint16_t version_minor;

 

    /** Identifier of module */

    const char *id;

 

    /** Name of this module */

    const char *name;

 

    /** Author/owner/implementor of the module */

    const char *author;

 

    /** Modules methods */

    struct hw_module_methods_t* methods;

 

    /** module's dso */

    void* dso;

 

    /** padding to 128 bytes, reserved for future use */

    uint32_t reserved[32-7];

 

} hw_module_t;

 

hardware/libhardware/include/hardware/hardware.h

/**

 * Every device data structure must begin with hw_device_t

 * followed by module specific public methods and attributes.

 */

typedef struct hw_device_t {

    /** tag must be initialized to HARDWARE_DEVICE_TAG */

    uint32_t tag;

 

    /** version number for hw_device_t */

    uint32_t version;

 

    /** reference to the module this device belongs to */

    struct hw_module_t* module;

 

    /** padding reserved for future use */

    uint32_t reserved[12];

 

    /** Close this device */

    int (*close)(struct hw_device_t* device);

 

} hw_device_t;

 

/**

 * Every device data structure must begin with hw_device_t

 * followed by module specific public methods and attributes.

 */

 

typedef struct alloc_device_t {

    struct hw_device_t common;

 

    /*

     * (*alloc)() Allocates a buffer in graphic memory with the requested

     * parameters and returns a buffer_handle_t and the stride in pixels to

     * allow the implementation to satisfy hardware constraints on the width

     * of a pixmap (eg: it may have to be multiple of 8 pixels).

     * The CALLER TAKES OWNERSHIP of the buffer_handle_t.

     *

     * Returns 0 on success or -errno on error.

     */

   

    int (*alloc)(struct alloc_device_t* dev,

            int w, int h, int format, int usage,

            buffer_handle_t* handle, int* stride);

 

    /*

     * (*free)() Frees a previously allocated buffer.

     * Behavior is undefined if the buffer is still mapped in any process,

     * but shall not result in termination of the program or security breaches

     * (allowing a process to get access to another process' buffers).

     * THIS FUNCTION TAKES OWNERSHIP of the buffer_handle_t which becomes

     * invalid after the call.

     *

     * Returns 0 on success or -errno on error.

     */

    int (*free)(struct alloc_device_t* dev,

            buffer_handle_t handle);

 

    /* This hook is OPTIONAL.

     *

     * If non NULL it will be caused by SurfaceFlinger on dumpsys

     */

    void (*dump)(struct alloc_device_t *dev, char *buff, int buff_len);

 

    void* reserved_proc[7];

} alloc_device_t;

上面給出了圖中列明的各種結構的定義,看起來挺複雜,讓我們從 GraphicBufferMapper說起,它的構造函數中的 GRALLOC_HARDWARE_MODULE_ID就是"gralloc" 字符串,通過 hw_get_module函數,得到了hw_module_t結構,實際上它是一個 private_module結構,該結構都是以hw_module_t結構開始的,所以在上圖中,我們把它們認爲是繼承關係,對於 gralloc模塊來說,這個private_module定義如下:

hardware/libhardware/modules/gralloc/gralloc.cpp 

struct private_module_t HAL_MODULE_INFO_SYM = {

    base: {

        common: {

            tag: HARDWARE_MODULE_TAG,

            version_major: 1,

            version_minor: 0,

            id: GRALLOC_HARDWARE_MODULE_ID,

            name: "Graphics Memory Allocator Module",

            author: "The Android Open Source Project",

            methods: &gralloc_module_methods

        },

        registerBuffer: gralloc_register_buffer,

        unregisterBuffer: gralloc_unregister_buffer,

        lock: gralloc_lock,

        unlock: gralloc_unlock,

    },

    framebuffer: 0,

    flags: 0,

    numBuffers: 0,

    bufferMask: 0,

    lock: PTHREAD_MUTEX_INITIALIZER,

    currentBuffer: 0,

};

其中

static struct hw_module_methods_t gralloc_module_methods = {

        open: gralloc_device_open

};

這裏的 gralloc_register_buffergralloc_unregister_buffer,gralloc_lock,gralloc_unlock ,定義在 hardware/libhardware/modules/gralloc/mapper.cpp ,在GraphicBufferMapper中調用的 mAllocMod->lock就是這裏的gralloc_lock 函數,其定義如下:

int gralloc_lock(gralloc_module_t const* module,

        buffer_handle_t handle, int usage,

        int l, int t, int w, int h,

        void** vaddr)

{

    // this is called when a buffer is being locked for software

    // access. in thin implementation we have nothing to do since

    // not synchronization with the h/w is needed.

    // typically this is used to wait for the h/w to finish with

    // this buffer if relevant. the data cache may need to be

    // flushed or invalidated depending on the usage bits and the

    // hardware.

 

    if (private_handle_t::validate(handle) < 0)

        return -EINVAL;

 

    private_handle_t* hnd = (private_handle_t*)handle;

    *vaddr = (void*)hnd->base;

    return 0;

}

從這裏我們看到,實際上只是取出了 handle中的一個地址,作爲返回地址,這個地址的作用是什麼,又是在哪裏賦值的呢?首先,這個地址是從 handle中取出的,這個handle是從哪裏來的呢?它是 GraphicBuffer調用lock 函數的時候,作爲參數傳遞進來的,也就是說它是存儲在 GraphicBuffer中的,那麼GraphicBuffer 又是從何而來的呢?是從服務器端通過 Binder傳遞過來的,在GraphicBuffer中的 GraphicBuffer::unflatten函數中讀取到的

status_t GraphicBuffer::unflatten(void const* buffer, size_t size,

        int fds[], size_t count)

{

    if (size < 8*sizeof(int)) return NO_MEMORY;

 

    int const* buf = static_cast(buffer);

    if (buf[0] != 'GBFR') return BAD_TYPE;

 

    const size_t numFds  = buf[6];

    const size_t numInts = buf[7];

 

    const size_t sizeNeeded = (8 + numInts) * sizeof(int);

    if (size < sizeNeeded) return NO_MEMORY;

 

    size_t fdCountNeeded = 0;

    if (count < fdCountNeeded) return NO_MEMORY;

 

    if (handle) {

        // free previous handle if any

        free_handle();

    }

 

    if (numFds || numInts) {

        width  = buf[1];

        height = buf[2];

        stride = buf[3];

        format = buf[4];

        usage  = buf[5];

        native_handle* h = native_handle_create(numFds, numInts);

        memcpy(h->data,          fds,     numFds*sizeof(int));

        memcpy(h->data + numFds, &buf[8], numInts*sizeof(int));

        handle = h;

    } else {

        width = height = stride = format = usage = 0;

        handle = NULL;

    }

 

    mOwner = ownHandle;

 

    if (handle != 0) {

        mBufferMapper.registerBuffer(handle);

    }

 

    return NO_ERROR;

}

要想讀懂這段代碼,首先要了解 native_handle的結構

system/core/include/cutils/native_handle.h

typedef struct native_handle

{

    int version;        /* sizeof(native_handle_t) */

    int numFds;         /* number of file-descriptors at &data[0] */

    int numInts;        /* number of ints at &data[numFds] */

    int data[0];        /* numFds + numInts ints */

} native_handle_t;

system/core/include/system/window.h

typedef const native_handle_t* buffer_handle_t;

native_handle_tdata 字段,比較特別,它在 native_handle_t中並不佔用內存,但是它指向 numInts後的內存,按照說明,numFds表示從 data[0]處開始,有幾個fd numInts表示從data[numFds] 開始有幾個 int數據,總體的大小就是numFds+numInts int,實際上,data 是一個指向私有結構的指針,對於 gralloc來說,這個結構定義如下:

hardware/libhardware/modules/gralloc/gralloc_priv.h

struct private_handle_t {

    struct native_handle nativeHandle;

   

    enum {

        PRIV_FLAGS_FRAMEBUFFER = 0x00000001

    };

 

    // file-descriptors

    int     fd;

    // ints

    int     magic;

    int     flags;

    int     size;

    int     offset;

 

    // FIXME: the attributes below should be out-of-line

    int     base;

    int     pid;

 

    static const int sNumInts = 6;

    static const int sNumFds = 1;

    static const int sMagic = 0x3141592;

。。。

}

也就是說,在 native_handle之後,緊接着這樣一個private_handel_t結構,在這裏只有一個 fd,除此之外還有6 int。這樣我們就從服務器端跨進程,得到了 native_handle

unflatten的最後動作是調用了registerBuffer ,這個函數實際上調用了 gralloc模塊的registerBuffer 函數,即 gralloc_register函數,該函數定義如下:

int gralloc_register_buffer(gralloc_module_t const* module,

        buffer_handle_t handle)

{

    if (private_handle_t::validate(handle) < 0)

        return -EINVAL;

 

    // if this handle was created in this process, then we keep it as is.

    int err = 0;

    private_handle_t* hnd = (private_handle_t*)handle;

    if (hnd->pid != getpid()) {

        void *vaddr;

        err = gralloc_map(module, handle, &vaddr);

    }

    return err;

}

其中調用的 gralloc_map函數定義如下:

static int gralloc_map(gralloc_module_t const* module,

        buffer_handle_t handle,

        void** vaddr)

{

    private_handle_t* hnd = (private_handle_t*)handle;

    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {

        size_t size = hnd->size;

        void* mappedAddress = mmap(0, size,

                PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);

        if (mappedAddress == MAP_FAILED) {

            LOGE("Could not mmap %s", strerror(errno));

            return -errno;

        }

        hnd->base = intptr_t(mappedAddress) + hnd->offset;

        //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p",

        //        hnd->fd, hnd->offset, hnd->size, mappedAddress);

    }

    *vaddr = (void*)hnd->base;

    return 0;

}

看到這裏,我們就明白了,原來所謂註冊的動作,實際上是根據從 Binder傳遞過來的handle 中的size fd,做了一個內存映射的操作,並把系統返回的地址保存在 handle中,並作爲返回值被返回出去。特別說明的是, fd之所以能夠在進程間傳遞,也是因爲在 Binder中對其進行了特殊處理,具體方法在前文中已經說明。

現在我們對客戶端的 lock過程已經很清楚了,但是還有一個流程我們還不清楚,即服務器端是如何進行 GraphicBuffer的分配的呢?

GraphicBuffer.cpp中,我們看到所謂 reallocate的過程,實際上是通過GraphicBufferAllocator進行真實的分配的, GraphicBuffer得到的只是一個handle,所以我們看看 GraphicBufferAllocator是如何完成分配動作的,先看看它的構造函數

GraphicBufferAllocator::GraphicBufferAllocator()

    : mAllocDev(0)

{

    hw_module_t const* module;

    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);

    LOGE_IF(err, "FATAL: can't find the %s module", GRALLOC_HARDWARE_MODULE_ID);

    if (err == 0) {

        gralloc_open(module, &mAllocDev);

    }

}

其中的 gralloc_open的定義如下:

hardware/libhardware/include/hardware/gralloc.h

static inline int gralloc_open(const struct hw_module_t* module,

        struct alloc_device_t** device) {

    return module->methods->open(module,

            GRALLOC_HARDWARE_GPU0, (struct hw_device_t**)device);

}

這裏使用到了 modulemethod open函數,從上面 module的定義,我們知道這個open函數就是 gralloc_device_open

hardware/libhardware/modules/gralloc/gralloc.cpp

int gralloc_device_open(const hw_module_t* module, const char* name,

        hw_device_t** device)

{

    int status = -EINVAL;

    if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {

        gralloc_context_t *dev;

        dev = (gralloc_context_t*)malloc(sizeof(*dev));

 

        /* initialize our state here */

        memset(dev, 0, sizeof(*dev));

 

        /* initialize the procs */

        dev->device.common.tag = HARDWARE_DEVICE_TAG;

        dev->device.common.version = 0;

        dev->device.common.module = const_cast(module);

        dev->device.common.close = gralloc_close;

 

        dev->device.alloc   = gralloc_alloc;

        dev->device.free    = gralloc_free;

 

        *device = &dev->device.common;

        status = 0;

    } else {

        status = fb_device_open(module, name, device);

    }

    return status;

}

從這裏我們知道,這個 device設備是通過module 打開的,這就是 moduledevice 之間的關係。在 GraphicBufferAllocator中調用的alloc 函數,就是 gralloc_alloc函數,

hardware/libhardware/modules/gralloc/gralloc.cpp

static int gralloc_alloc(alloc_device_t* dev,

        int w, int h, int format, int usage,

        buffer_handle_t* pHandle, int* pStride)

{

    if (!pHandle || !pStride)

        return -EINVAL;

 

    size_t size, stride;

 

    int align = 4;

    int bpp = 0;

    switch (format) {

        case HAL_PIXEL_FORMAT_RGBA_8888:

        case HAL_PIXEL_FORMAT_RGBX_8888:

        case HAL_PIXEL_FORMAT_BGRA_8888:

            bpp = 4;

            break;

        case HAL_PIXEL_FORMAT_RGB_888:

            bpp = 3;

            break;

        case HAL_PIXEL_FORMAT_RGB_565:

        case HAL_PIXEL_FORMAT_RGBA_5551:

        case HAL_PIXEL_FORMAT_RGBA_4444:

            bpp = 2;

            break;

        default:

            return -EINVAL;

    }

    size_t bpr = (w*bpp + (align-1)) & ~(align-1);

    size = bpr * h;

    stride = bpr / bpp;

 

    int err;

    if (usage & GRALLOC_USAGE_HW_FB) {

        err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);

    } else {

        err = gralloc_alloc_buffer(dev, size, usage, pHandle);

    }

 

    if (err < 0) {

        return err;

    }

 

    *pStride = stride;

    return 0;

}

我們以軟件分配爲例,它將調用 gralloc_alloc_buffer

hardware/libhardware/modules/gralloc/gralloc.cpp

static int gralloc_alloc_buffer(alloc_device_t* dev,

        size_t size, int usage, buffer_handle_t* pHandle)

{

    int err = 0;

    int fd = -1;

 

    size = roundUpToPageSize(size);

   

    fd = ashmem_create_region("gralloc-buffer", size);

    if (fd < 0) {

        LOGE("couldn't create ashmem (%s)", strerror(-errno));

        err = -errno;

    }

 

    if (err == 0) {

        private_handle_t* hnd = new private_handle_t(fd, size, 0);

        gralloc_module_t* module = reinterpret_cast(

                dev->common.module);

        err = mapBuffer(module, hnd);

        if (err == 0) {

            *pHandle = hnd;

        }

    }

   

    LOGE_IF(err, "gralloc failed err=%s", strerror(-err));

   

    return err;

}

hardware/libhardware/modules/gralloc/mapper.cpp

int mapBuffer(gralloc_module_t const* module,

        private_handle_t* hnd)

{

    void* vaddr;

    return gralloc_map(module, hnd, &vaddr);

}

ashmem_create_region 函數根據 size創建了匿名的共享內存塊,以文件名 fd來標識,最後還是通過mapper.cpp中的 gralloc_map函數映射到內存中,其過程與客戶端是一樣的,這樣,我們對整個的分配過程就很清晰了,其過程可描述如下:

 

至此,從ViewRootImpl.setView方法來看,該方法的作用就是把當前ViewRootImpl.IWindow加入到session中,在服務端WMS上創建對應的WindowState,然後通過SurfaceFlinger創建ISurface實例,並把它通過SurfaceControl與ViewRootImpl.mSurface綁定

 

4.Surface的使用

ViewRootImpl.draw函數對Surface的使用如下:

ViewRootImpl.draw(){

    Surface surface = mSurface;

    。。。

    Canvas canvas = surface.lockCanvas(null);

    。。。

    mView.draw(canvas);

    。。。

    surface.unlockCanvasAndPost(canvas);

}

mSurface在setView的時候就被綁定了native ISurface實例,lockCanvas將得到一個分配了Asm內存的GraphicBuffer,這個buffer中的內存地址,設置給SkBitmap,這個bitmap又設置給canvas,後續的畫圖操作都在這個canvas上進行,unlockCanvasAndPost操作,將把GraphicBuffer在SurfaceFlinger服務端入隊列,然後等待flip

 

總體來說,上面描述的類及其關係,即所在進程的關係如下:


 

本圖中需要特別說明的是,Surface java對象,既與SurfaceControl綁定,又與Surface native對象綁定,他們是有不同的目的的。

在前面的分析中,我們知道addView的時候,最終得到的ISurface實例是存儲在SurfaceControl中,SurfaceControl與ViewRootImpl中的Surface對象綁定的,也就是說android在繪製view這類控件的時候,是走的SurfaceControl這條路的

除此之外,android還提供了另外一條路,Surface native對象可以通過SurfaceControl對象來初始化,可以使用SurfaceTexture初始化,該native對象最後與Surface java對象綁定。

ViewRootImpl.draw(boolean fullRedrawNeeded) {

        Surface surface = mSurface;

                ....

                canvas = surface.lockCanvas(dirty);

                ....

                mView.draw(canvas);

                ....

                surface.unlockCanvasAndPost(canvas);

}

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章