Android系统的SurfaceFlinger服务有两种启动方式:1)在SystemServer进程中以服务线程的方式提供服务;2)启动SurfaceFlinger独立的进程通过服务。第一种方式是在SystemServer进程启动过程中启动SurfaceFlinger服务的,而第二中方式是在Android启动脚本init.rc中配置SurfaceFlinger服务,通过init进程来启动的。下面就分别介绍SurfaceFlinger的两种启动方式。
1 服务线程启动方式
在Android 开关机动画显示源码分析中已经简要介绍过SurfaceFlinger服务的这种启动方式,在SystemServer进程的init1阶段,通过JNI调用system_init()函数来启动SurfaceFlinger:
frameworks\base\cmds\system_server\library\system_init.cpp
extern "C" status_t system_init(){ ALOGI("Entered system_init()"); sp<ProcessState> proc(ProcessState::self()); sp<IServiceManager> sm = defaultServiceManager(); ALOGI("ServiceManager: %p\n", sm.get()); sp<GrimReaper> grim = new GrimReaper(); sm->asBinder()->linkToDeath(grim, grim.get(), 0); char propBuf[PROPERTY_VALUE_MAX]; property_get("system_init.startsurfaceflinger", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // Start the SurfaceFlinger SurfaceFlinger::instantiate(); } ....}
SurfaceFlinger继承于BinderService模板类,BinderService的instantiate函数实现:
static void instantiate() { publish(); }
static status_t publish(bool allowIsolated = false) { sp<IServiceManager> sm(defaultServiceManager()); return sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated);}函数首先得到ServiceManager的Binder代理对象,然后构造一个SurfaceFlinger对象,并注册到ServiceManager进程中。
如果system_init.startsurfaceflinger属性的值等于0,意味着SurfaceFlinger是以服务进程的方式启动的。
2.服务进程启动方式
当system_init.startsurfaceflinger属性的值设置为0时,就必须在init.rc中配置SurfaceFlinger服务,通过init进程启动。
当SurfaceFlinger以服务进程的方式启动时,必现提供进程入口函数main,在frameworks\native\cmds\surfaceflinger\main_surfaceflinger.cpp中实现:
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;}函数调用SurfaceFlinger类的publishAndJoinThreadPool方法启动构造SurfaceFlinger对象并注册到ServiceManager进程中,然后调用setThreadPoolMaxThreadCount函数来设置SurfaceFlinger进程的最大Binder线程数。
static void publishAndJoinThreadPool(bool allowIsolated = false) { sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), allowIsolated); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool();}和前面的publish函数一样,首先得到ServiceManager的Binder代理对象,然后构造一个SurfaceFlinger对象,并注册到ServiceManager进程中,只不过这里额外调用了ProcessState::self()->startThreadPool()来启动Binder线程池,并且将当前进程的主线程注册到Binder线程池中,对于SurfaceFlinger服务进程来说,为了接收客户端的请求,SurfaceFlinger服务进程必现启动Binder线程池。如果SurfaceFlinger以服务线程的方式在SystemServer进程中启动的话,就无需启动Binder线程,因为SurfaceFlinger服务驻留在SystemServer进程中,而SysteServer进程自己维护了一个Binder线程池。
3.启动SurfaceFlinger
SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), Thread(false), mTransactionFlags(0), mTransationPending(false), mLayersRemoved(false), mBootTime(systemTime()), mVisibleRegionsDirty(false), mHwWorkListDirty(false), mElectronBeamAnimationMode(0), mDebugRegion(0), mDebugDDMS(0), mDebugDisableHWC(0), mDebugDisableTransformHint(0), mDebugInSwapBuffers(0), mLastSwapBufferTime(0), mDebugInTransaction(0), mLastTransactionTime(0), mBootFinished(false), mSecureFrameBuffer(0){ init();}构造过程仅仅初始化了SurfaceFlinger的成员变量,同时调用了父类BnSurfaceComposer的构造函数。最后使用init方法来作一些初始化工作。
void SurfaceFlinger::init(){ ALOGI("SurfaceFlinger is starting"); char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.showupdates", value, "0"); mDebugRegion = atoi(value); property_get("ro.bootmode", value, "mode"); if (!(strcmp(value, "engtest") && strcmp(value, "special") && strcmp(value, "wdgreboot") && strcmp(value, "unknowreboot") && strcmp(value, "panic"))) { SurfaceFlinger::sBootanimEnable = false; }}读取开机模式属性ro.bootmode来决定是否要显示开机动画,关于开机动画在Android 开关机动画显示源码分析中介绍了。由于SurfaceFlinger继承于RefBase类,同时实现了RefBase的onFirstRef()方法,因此在第一次引用SurfaceFlinger对象时,onFirstRef()函数自动被调用:
void SurfaceFlinger::onFirstRef(){ mEventQueue.init(this); run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY); // Wait for the main thread to be done with its initialization mReadyToRunBarrier.wait();}mEventQueue是MessageQueue类型变量,定义在frameworks\native\services\surfaceflinger\MessageQueue.h这里调用init函数初始化mEventQueue消息队列
void MessageQueue::init(const sp<SurfaceFlinger>& flinger){ mFlinger = flinger; mLooper = new Looper(true); mHandler = new Handler(*this);}mReadyToRunBarrier为Barrier类型的变量,用于阻塞,启动线程运行,对象构造时,状态初始化为CLOSED,因此在调用它的wait方法时,当前SurfaceFlinger线程睡眠等待SystemServer主线程调用readyToRun()函数完成SurfaceFlinger运行前的初始化工作。
inline Barrier() : state(CLOSED) { }void wait() const { Mutex::Autolock _l(lock); while (state == CLOSED) { cv.wait(lock); }}SurfaceFlinger继承于Thread类,因此构造一个SurfaceFlinger对象,其实就是创建一个线程,当调用其run方法时,就是启动该线程的运行,在SurfaceFlinger线程运行前,需要主线程初始化OpenGL库,因此在主线程完成初始化工作前,需要让SurfaceFlinger线程睡眠等待,主线程初始化工作:
status_t SurfaceFlinger::readyToRun(){ ALOGI( "SurfaceFlinger's main thread ready to run. ""Initializing graphics H/W..."); // we only support one display currently int dpy = 0; { //初始化主显示屏,即从SurfaceFlinger中取出第0号GraphicPlane GraphicPlane& plane(graphicPlane(dpy)); //创建DisplayHardware,并和显示屏绑定 DisplayHardware* const hw = new DisplayHardware(this, dpy); plane.setDisplayHardware(hw); } //创建一块大小为4k的匿名共享内存,用于共享显示屏幕信息 mServerHeap = new MemoryHeapBase(4096,MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap"); ALOGE_IF(mServerHeap==0, "can't create shared memory dealer"); //将该匿名共享内存的首地址转换为surface_flinger_cblk_t类型的指针,表明该共享内存存储surface_flinger_cblk_t结构体数据 mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase()); ALOGE_IF(mServerCblk==0, "can't get to shared control block's address"); new(mServerCblk) surface_flinger_cblk_t; //从显示屏的DisplayHardware中得到屏幕的宽高,并设置为当前主显示屏 const GraphicPlane& plane(graphicPlane(dpy)); const DisplayHardware& hw = plane.displayHardware(); const uint32_t w = hw.getWidth(); const uint32_t h = hw.getHeight(); const uint32_t f = hw.getFormat(); hw.makeCurrent(); //将屏幕信息保存到匿名共享内存中,从而共享给所有进程 mServerCblk->connected |= 1<<dpy; display_cblk_t* dcblk = mServerCblk->displays + dpy; memset(dcblk, 0, sizeof(display_cblk_t)); dcblk->w = plane.getWidth(); dcblk->h = plane.getHeight(); dcblk->format = f; dcblk->orientation = ISurfaceComposer::eOrientationDefault; dcblk->xdpi = hw.getDpiX(); dcblk->ydpi = hw.getDpiY(); dcblk->fps = hw.getRefreshRate(); dcblk->density = hw.getDensity(); //初始化OpenGL|ES glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glPixelStorei(GL_PACK_ALIGNMENT, 4); glEnableClientState(GL_VERTEX_ARRAY); glShadeModel(GL_FLAT); glDisable(GL_DITHER); glDisable(GL_CULL_FACE); const uint16_t g0 = pack565(0x0F,0x1F,0x0F); const uint16_t g1 = pack565(0x17,0x2f,0x17); const uint16_t wormholeTexData[4] = { g0, g1, g1, g0 }; glGenTextures(1, &mWormholeTexName); glBindTexture(GL_TEXTURE_2D, mWormholeTexName); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,GL_RGB, GL_UNSIGNED_SHORT_5_6_5, wormholeTexData); const uint16_t protTexData[] = { pack565(0x03, 0x03, 0x03) }; glGenTextures(1, &mProtectedTexName); glBindTexture(GL_TEXTURE_2D, mProtectedTexName); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0,GL_RGB, GL_UNSIGNED_SHORT_5_6_5, protTexData); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // put the origin in the left-bottom corner glOrthof(0, w, 0, h, 0, 1); // l=0, r=w ; b=0, t=h // 启动EventThread线程 mEventThread = new EventThread(this); mEventQueue.setEventThread(mEventThread); hw.startSleepManagement(); //主线程已经完成初始化工作,唤醒睡眠等待中的SurfaceFlinger线程接收客户端的请求 mReadyToRunBarrier.open(); //启动开机动画 startBootAnim(); return NO_ERROR;}函数首先初始化主显示屏,为该GraphicPlane创建DisplayHardware对象,然后创建一块匿名共享内存,用于保存显示屏幕信息,同时共享给系统的其他进程访问,接着初始化OpenGL库,同时启动EventThread线程,唤醒SurfaceFlinger线程,并启动开机动画。
1)获取GraphicPlane
GraphicPlane& SurfaceFlinger::graphicPlane(int dpy){ return const_cast<GraphicPlane&>(const_cast<SurfaceFlinger const *>(this)->graphicPlane(dpy));}//Android4.1只支持1个屏幕显示,#define DISPLAY_COUNT 1const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const{ ALOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy); const GraphicPlane& plane(mGraphicPlanes[dpy]); return plane;}
2)构造DisplayHardware对象
DisplayHardware::DisplayHardware(const sp<SurfaceFlinger>& flinger,uint32_t dpy): DisplayHardwareBase(flinger, dpy), mFlinger(flinger), mFlags(0), mHwc(0){ init(dpy);}构造DisplayHardware对象前,首先会构造其父类DisplayHardwareBase对象。
DisplayHardwareBase::DisplayHardwareBase(const sp<SurfaceFlinger>& flinger, uint32_t displayIndex) { mScreenAcquired = true; mDisplayEventThread = new DisplayEventThread(flinger);}在DisplayHardwareBase对象内部创建一个DisplayEventThread线程
DisplayHardwareBase::DisplayEventThread::DisplayEventThread(const sp<SurfaceFlinger>& flinger) : Thread(false), mFlinger(flinger) {}然后初始化DisplayHardware
void DisplayHardware::init(uint32_t dpy){ //创建FramebufferNativeWindow对象 mNativeWindow = new FramebufferNativeWindow(); //在构造FramebufferNativeWindow对象时,通过打开Gralloc硬件抽象层模块,得到framebuffer_device_t framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); if (!fbDev) { ALOGE("Display subsystem failed to initialize. check logs. exiting..."); exit(0); } int format; ANativeWindow const * const window = mNativeWindow.get(); //查询指定window的format信息 window->query(window, NATIVE_WINDOW_FORMAT, &format); mDpiX = mNativeWindow->xdpi; mDpiY = mNativeWindow->ydpi; mRefreshRate = fbDev->fps; if (mDpiX == 0 || mDpiY == 0) { ALOGE("invalid screen resolution from fb HAL (xdpi=%f, ydpi=%f), ""defaulting to 160 dpi", mDpiX, mDpiY); mDpiX = mDpiY = 160; } class Density { //通过读取属性得到屏幕像素密度 static int getDensityFromProperty(char const* propName) { char property[PROPERTY_VALUE_MAX]; int density = 0; if (property_get(propName, property, NULL) > 0) { density = atoi(property); } return density; } public: //提供两个得到屏幕像素密度的接口,getEmuDensity用于得到模拟器的像素密度;getBuildDensity用于得到编译指定的屏幕像素密度 static int getEmuDensity() { return getDensityFromProperty("qemu.sf.lcd_density"); } static int getBuildDensity() { return getDensityFromProperty("ro.sf.lcd_density"); } }; // The density of the device is provided by a build property mDensity = Density::getBuildDensity() / 160.0f; if (mDensity == 0) { // the build doesn't provide a density -- this is wrong! use xdpi instead ALOGE("ro.sf.lcd_density must be defined as a build property"); mDensity = mDpiX / 160.0f; } if (Density::getEmuDensity()) { // if "qemu.sf.lcd_density" is specified, it overrides everything mDpiX = mDpiY = mDensity = Density::getEmuDensity(); mDensity /= 160.0f; } /* FIXME: this is a temporary HACK until we are able to report the refresh rate * properly from the HAL. The WindowManagerService now relies on this value. */#ifndef REFRESH_RATE mRefreshRate = fbDev->fps;#else mRefreshRate = REFRESH_RATE;#warning "refresh rate set via makefile to REFRESH_RATE"#endif mRefreshPeriod = nsecs_t(1e9 / mRefreshRate); EGLint w, h, dummy; EGLint numConfigs=0; EGLSurface surface; EGLContext context; EGLBoolean result; status_t err; // initialize EGL EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE, 0, EGL_NONE }; // debug: disable h/w rendering char property[PROPERTY_VALUE_MAX]; if (property_get("debug.sf.hw", property, NULL) > 0) { if (atoi(property) == 0) { ALOGW("H/W composition disabled"); attribs[2] = EGL_CONFIG_CAVEAT; attribs[3] = EGL_SLOW_CONFIG; } } // TODO: all the extensions below should be queried through // eglGetProcAddress(). EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(display, NULL, NULL); eglGetConfigs(display, NULL, 0, &numConfigs); EGLConfig config = NULL; err = selectConfigForPixelFormat(display, attribs, format, &config); ALOGE_IF(err, "couldn't find an EGLConfig matching the screen format"); EGLint r,g,b,a; eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r); eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g); eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b); eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a); if (mNativeWindow->isUpdateOnDemand()) { mFlags |= PARTIAL_UPDATES; } if (eglGetConfigAttrib(display, config, EGL_CONFIG_CAVEAT, &dummy) == EGL_TRUE) { if (dummy == EGL_SLOW_CONFIG) mFlags |= SLOW_CONFIG; } //Create our main surface surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL); eglQuerySurface(display, surface, EGL_WIDTH, &mWidth); eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight); if (mFlags & PARTIAL_UPDATES) { // if we have partial updates, we definitely don't need to // preserve the backbuffer, which may be costly. eglSurfaceAttrib(display, surface,EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED); } //Create our OpenGL ES context EGLint contextAttributes[] = {#ifdef EGL_IMG_context_priority#ifdef HAS_CONTEXT_PRIORITY#warning "using EGL_IMG_context_priority" EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG,#endif#endif EGL_NONE, EGL_NONE }; context = eglCreateContext(display, config, NULL, contextAttributes); mDisplay = display; mConfig = config; mSurface = surface; mContext = context; mFormat = fbDev->format; mPageFlipCount = 0; // Gather OpenGL ES extensions result = eglMakeCurrent(display, surface, surface, context); if (!result) { ALOGE("Couldn't create a working GLES context. check logs. exiting..."); exit(0); } GLExtensions& extensions(GLExtensions::getInstance()); extensions.initWithGLStrings( glGetString(GL_VENDOR), glGetString(GL_RENDERER), glGetString(GL_VERSION), glGetString(GL_EXTENSIONS), eglQueryString(display, EGL_VENDOR), eglQueryString(display, EGL_VERSION), eglQueryString(display, EGL_EXTENSIONS)); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims); // Unbind the context from this thread eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); // initialize the H/W composer mHwc = new HWComposer(mFlinger, *this, mRefreshPeriod); if (mHwc->initCheck() == NO_ERROR) { mHwc->setFrameBuffer(mDisplay, mSurface); }}
3)创建匿名共享内存保存屏幕信息
//创建一块大小为4k的匿名共享内存,用于共享显示屏幕信息mServerHeap = new MemoryHeapBase(4096,MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");ALOGE_IF(mServerHeap==0, "can't create shared memory dealer");//将该匿名共享内存的首地址转换为surface_flinger_cblk_t类型的指针,表明该共享内存存储surface_flinger_cblk_t结构体数据mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());ALOGE_IF(mServerCblk==0, "can't get to shared control block's address");new(mServerCblk) surface_flinger_cblk_t;//从显示屏的DisplayHardware中得到屏幕的宽高,并设置为当前主显示屏const GraphicPlane& plane(graphicPlane(dpy));const DisplayHardware& hw = plane.displayHardware();const uint32_t w = hw.getWidth();const uint32_t h = hw.getHeight();const uint32_t f = hw.getFormat();hw.makeCurrent();//将屏幕信息保存到匿名共享内存中,从而共享给所有进程mServerCblk->connected |= 1<<dpy;display_cblk_t* dcblk = mServerCblk->displays + dpy;memset(dcblk, 0, sizeof(display_cblk_t));dcblk->w = plane.getWidth();dcblk->h = plane.getHeight();dcblk->format = f;dcblk->orientation = ISurfaceComposer::eOrientationDefault;dcblk->xdpi = hw.getDpiX();dcblk->ydpi = hw.getDpiY();dcblk->fps = hw.getRefreshRate();dcblk->density = hw.getDensity();
4)SurfaceFlinger线程模型
无论SurfaceFlinger是以服务线程启动还是已服务进程启动,在启动过程中,主线程启动SurfaceFlinger线程,EventThread线程及DisplayEventThread线程
EventThread线程启动过程:
EventThread::EventThread(const sp<SurfaceFlinger>& flinger) : mFlinger(flinger), mHw(flinger->graphicPlane(0).editDisplayHardware()), mLastVSyncTimestamp(0), mVSyncTimestamp(0), mUseSoftwareVSync(false), mDeliveredEvents(0), mDebugVsyncEnabled(false){}void EventThread::onFirstRef() { mHw.setVSyncHandler(this); run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);}DisplayEventThread线程启动过程:
void DisplayHardwareBase::startSleepManagement() const { if (mDisplayEventThread->initCheck() == NO_ERROR) { mDisplayEventThread->run("DisplayEventThread", PRIORITY_URGENT_DISPLAY); } else { ALOGW("/sys/power/wait_for_fb_{wake|sleep} don't exist"); }}