当前位置: 代码迷 >> Android >> Android SurfaceFlinger服务起动过程源码分析
  详细解决方案

Android SurfaceFlinger服务起动过程源码分析

热度:17   发布时间:2016-04-28 08:00:45.0
Android SurfaceFlinger服务启动过程源码分析

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属性值来决定是否在SystemServer进程中启动SurfaceFlinger服务,因此如果要在SystemServer中启动SurfaceFlinger,就必须设置system_init.startsurfaceflinger属性
如果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");    }}

  相关解决方案