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.Window,WindowManager ,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   是一一对应的,   ISurfaceComposerClient SurfaceComposerClient   也是一一对应的,而   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);

}

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值