详解Android SurfaceFinger服务

概述

SurfaceFlinger是android平台的显示服务,为移动互联网时代的内容呈现和交互提供了平台级的基础。本文以Android4.2的源代码和架构为例,详细介绍SurfaceFlinger服务。

相关类图

启动

SurfaceFlinger服务的源代码位于frameworks/native/cmds/surfaceflinger下:

int main(int argc, char** argv) { SurfaceFlinger::publishAndJoinThreadPool(true); // When SF is launched in its own process, limit the number of // binder threads to 4. ProcessState::self()->setThreadPoolMaxThreadCount(4); return 0;}

为android平台上最常见的native BinderService启动方式。

下边结合binder上层接口粗略分析该段程序。

将"SurfaceFlinger::publishAndJoinThreadPool(true);"

扩展开变为:

sp<IServiceManager> sm(defaultServiceManager());sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); // 向servicemanager注册SurfaceFinger服务,以“SurfaceFlinger”作为名字/标识ProcessState::self()->startThreadPool();IPCThreadState::self()->joinThreadPool();

ProcessState为每进程的记录binder进程状态的类。主要职责在于:

打开binder设备并将binder事务内存映射到本进程地址空间的最开始,尺寸为BINDER_VM_SIZE记录contextobject(一般为servicemanager代理对象)孵化线程/管理线程池IBinder和handle之间的转换和查询ProcessState::self()->startThreadPool();通过创建一个额外线程(自动进入looper状态)来启动线程池,IPCThreadState::self()->joinThreadPool();IPCThreadState为每线程(通过编程本地存储实现)的管理binder thread状态的类,同时负责与binder设备之间的数据交换,其成员:ParcelmIn;ParcelmOut;承担着binder的flat/unflat、发出请求到binder、从binder设备接收client端的请求等任务。

这样子主线程也进入looper模式,现在进入joinThreadPool方法:

binder通信的主要细节就在此方法中,主要思想便是通过talkWithDriver来取到本进程接收到的binder请求并将其反序列化为mIn身上,读出cmd并执行之,摘取几个重要的cmd如下:

BR_TRANSACTION:代表一次binder事务,最常见的便是RPC调用了

binder_transaction_data tr;……if (tr.target.ptr) {sp<BBinder> b((BBinder*)tr.cookie);const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);if (error < NO_ERROR) reply.setError(error);} else {const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);if (error < NO_ERROR) reply.setError(error);}

binder_transaction_data身上带有服务端的BBinder(client端第一次从servicemanager查询到服务端时被告知并由binder driver记录),

当tr.target.ptr非空时,通过该BBinder对象的transact函数来完成RPC。否则意味着对context_object(通常为本进程内的BpServiceManager对象,且对应handle为0 )的请求。

BBinder的子类通过onTransact函数来服务各种RPC调用。在本文中,便是SurfaceFlinger对象的onTransact函数来应对client的请求。

BR_SPAWN_LOOPER:

前边启动过程中,binder thread包括主线程(SurfaceFlinger对象构造过程中也创建了额外辅助进程,但不是binder thread,排除在外,在本文后半部分分析)一共是两个。当有多个client请求时,势必binder thread不够用(binder driver簿记binder thread的各种信息),此时binder driver便post BR_SPAWN_LOOPER类型的cmd,让本进程预先孵化下一个binder thread,且此后孵化的线程不会进入looper模式(主要处理线程),只是登记为looper(目前在driver中未看出来两者明显区别)

另外,当本进程需要其他服务的协助的时候呢,本进程也需要作为client来发起binder请求,此时便用到了BpBinder::transact()函数,BpBinder成员mHandle用来引用远端对象,作为参数传递给IPCThreadState::self()->transact()来完成。其原理与前述接受binder请求的过程相反,不再赘述。

SurfaceFlinger构造

此步骤是前述启动步骤中的一小步,但也是展现出特定service与众不同的最大一步。

如文件第一部分所列类图所示,SurfaceFlinger继承自多个基类:

class SurfaceFlinger : public BinderService<SurfaceFlinger>,public BnSurfaceComposer,private IBinder::DeathRecipient,private Thread,private HWComposer::EventHandler构造函数非常轻量级,只获取了几个系统debug设置。

在ServiceManager addservice时第一次引用刚创建的SurfaceFinger对象,其基类RefBase的onFirstRef被调用:

void SurfaceFlinger::onFirstRef(){mEventQueue.init(this);run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);// Wait for the main thread to be done with its initializationmReadyToRunBarrier.wait();}初始化EventQueue,并建立Looper/Handler这对好基友。

接下来启动自己(SurfaceFlinger也是Thread对象),

然后主线程阻塞住直到ReadyToRun(Thread真正启动前的一次性初始化函数)被调用。

接下来咱们转到ReadyToRun函数,鉴于该函数如一枚知性的熟女——深有内涵:

ALOGI( "SurfaceFlinger’s main thread ready to run. ""Initializing graphics H/W…");// initialize EGL for the default displaymEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);eglInitialize(mEGLDisplay, NULL, NULL);// Initialize the H/W composer object. There may or may not be an// actual hardware composer underneath.mHwc = new HWComposer(this,*static_cast<HWComposer::EventHandler *>(this));// initialize the config and contextEGLint format = mHwc->getVisualID();mEGLConfig = selectEGLConfig(mEGLDisplay, format);mEGLContext = createGLContext(mEGLDisplay, mEGLConfig);LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,"couldn’t create EGLContext");// initialize our non-virtual displaysfor (size_t i=0 ; i<DisplayDevice::NUM_DISPLAY_TYPES ; i++) {DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);mDefaultDisplays[i] = new BBinder();wp<IBinder> token = mDefaultDisplays[i];// set-up the displays that are already connectedif (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {// All non-virtual displays are currently considered secure.bool isSecure = true;mCurrentState.displays.add(token, DisplayDeviceState(type));sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i);sp<SurfaceTextureClient> stc = new SurfaceTextureClient(static_cast< sp<ISurfaceTexture> >(fbs->getBufferQueue()));sp<DisplayDevice> hw = new DisplayDevice(this,type, isSecure, token, stc, fbs, mEGLConfig);if (i > DisplayDevice::DISPLAY_PRIMARY) {// FIXME: currently we don’t get blank/unblank requests// for displays other than the main display, so we always// assume a connected display is unblanked.ALOGD("marking display %d as acquired/unblanked", i);hw->acquireScreen();}mDisplays.add(token, hw);}}// we need a GL context current in a few places, when initializing// OpenGL ES (see below), or creating a layer,// or when a texture is (asynchronously) destroyed, and for that// we need a valid surface, so it’s convenient to use the main display// for that.sp<const DisplayDevice> hw(getDefaultDisplayDevice());// initialize OpenGL ESDisplayDevice::makeCurrent(mEGLDisplay, hw, mEGLContext);initializeGL(mEGLDisplay);// start the EventThreadmEventThread = new EventThread(this);mEventQueue.setEventThread(mEventThread);// initialize our drawing statemDrawingState = mCurrentState;// We’re now ready to accept clients…mReadyToRunBarrier.open();// set initial conditions (e.g. unblank default device)initializeDisplays();// start boot animationstartBootAnim();return NO_ERROR;

我们将其曼妙身段划分为如下:

下边摘取其中一些关键步骤分析:

EGL初始化代替你主持夕阳的葬礼。

详解Android SurfaceFinger服务

相关文章:

你感兴趣的文章:

标签云: