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

}

 

 

 

 

 

 

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