欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

荐 Android 图形架构 之二—— SurfaceFlinger 启动和连接

程序员文章站 2022-04-13 23:35:18
上一篇文章从全局来分析了Android 图形架构,本篇文章来分析SurfaceFlinger,surface的创建、图像的处理,管理设备的帧缓冲区等等,它是图像流的消费者,是本系列文章的核心SurfaceFlinger的启动过程启动概述SurfaceFlinger服务是一个独立进程。关于硬件方面的服务都在 frameworks/native/services/ 文件夹下,例如:audiomanager、powermanager、inputflinger、sensorservice、surfacefl...

前言

Android 图形架构 之一 ——概述
Android 图形架构 之二—— SurfaceFlinger 创建和连接
Android 图形架构 之三—— 创建Surface
Android 图形架构 之四——图形缓冲区GraphicBuffer
Android 图形架构 之五——Activity、WindowManagerService、Surface的关系
Android图形架构 之六——硬件VSync、VSync-app、Vsync-sf
Android图形架构 之七——SurfaceFlinger 合成Layer

上一篇文章从全局来分析了Android 图形架构,本篇文章来分析SurfaceFlinger,surface的创建、图像的处理,管理设备的帧缓冲区等等,它是图像流的消费者,是本系列文章的核心

一、SurfaceFlinger的启动过程

启动概述

SurfaceFlinger服务是一个独立进程。

关于硬件方面的服务都在 frameworks/native/services/ 文件夹下,例如:audiomanager、powermanager、inputflinger、sensorservice、surfaceflinger等。我们接下来

SurfaceFlinger服务配置,位于frameworks/native/services/surfaceflinger/surfaceflinger.rc中:

service surfaceflinger /system/bin/surfaceflinger
    class core animation
    user system
    group graphics drmrpc readproc
    onrestart restart zygote
    writepid /dev/stune/foreground/tasks
    socket pdx/system/vr/display/client     stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
    socket pdx/system/vr/display/manager    stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
    socket pdx/system/vr/display/vsync      stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0

SurfaceFlinger服务配置,位于frameworks/native/services/surfaceflinger/Android.mk 中:

###############################################################
# build surfaceflinger's executable
include $(CLEAR_VARS)

LOCAL_CFLAGS:= -DLOG_TAG=\"SurfaceFlinger\"
# SurfaceFlinger启动文件
LOCAL_SRC_FILES:= \
    main_surfaceflinger.cpp 

LOCAL_SHARED_LIBRARIES := \
    libsurfaceflinger \
    libcutils \
    liblog \
    libbinder \
    libutils
    
# SurfaceFlinger是个动态库
LOCAL_MODULE:= surfaceflinger

ifdef TARGET_32_BIT_SURFACEFLINGER
LOCAL_32_BIT_ONLY := true
endif

include $(BUILD_EXECUTABLE)

从Makefile文件可以看出,相关依赖和主文件会被编译成libsurfaceflinger.so,然后SurfaceFlinger是对库的一个“封装调用”,里面有个main_surfaceflinger.cpp,我们可以沿着它的main函数往下分析

SurfaceFlinger流程图,荐
                                                        Android 图形架构 之二—— SurfaceFlinger 启动和连接

启动过程

SurfaceFlinger的main函数在framework/native/services/surfaceflinger/main_surfaceflinger.cpp中:

代码一:
int main(int, char**) {
    // When SF is launched in its own process, limit the number of
    // binder threads to 4.
    //在该进程设置了binder线程池最大数为4
    ProcessState::self()->setThreadPoolMaxThreadCount(4);

    // start the thread pool
    //将当前线程加入到这个Binder线程池中去。例如:app进程通过binder通信,通知SurfaceFlinger进行渲染 
    sp<ProcessState> ps(ProcessState::self());
    ps->startThreadPool();

    // instantiate surfaceflinger
    //创建一个SurfaceFlinger强引用对象
    sp<SurfaceFlinger> flinger = new SurfaceFlinger();

#if defined(HAVE_PTHREADS)
    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
#endif
    set_sched_policy(0, SP_FOREGROUND);

    // initialize before clients can connect
    //SurfaceFlinger 初始化
    flinger->init();

    // publish surface flinger
    //把SurfaceFlinger服务注册到ServiceManager中
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);

    // run in this thread
    //运行线程,无限循环等待数据到来
    flinger->run();

    return 0;
}

接下来重点分析 创建SurfaceFlinger对象,执行init函数,和运行UI渲染流程。

创建SurfaceFlinger对象

new一个SurfaceFlinger对象,并赋给强引用指针。我们先看看它的构造函数,位于frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp中:

代码二:
SurfaceFlinger::SurfaceFlinger()
    :   BnSurfaceComposer(),
        mTransactionFlags(0),
        mTransactionPending(false),
        mAnimTransactionPending(false),
        mLayersRemoved(false),
        mRepaintEverything(0),
        mRenderEngine(NULL),
        mBootTime(systemTime()),
        mVisibleRegionsDirty(false),
        mHwWorkListDirty(false),
        mAnimCompositionPending(false),
        mDebugRegion(0),
        mDebugDDMS(0),
        mDebugDisableHWC(0),
        mDebugDisableTransformHint(0),
        mDebugInSwapBuffers(0),
        mLastSwapBufferTime(0),
        mDebugInTransaction(0),
        mLastTransactionTime(0),
        mBootFinished(false),
        mPrimaryHWVsyncEnabled(false),//主显屏硬件VSync信号关闭
        mHWVsyncAvailable(false),
        mDaltonize(false),
        mHasColorMatrix(false)
{
    ALOGI("SurfaceFlinger is starting");
    //一些调试变量,忽略一下内容
    // debugging stuff...
    char value[PROPERTY_VALUE_MAX];

    property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
    mGpuToCpuSupported = !atoi(value);

    property_get("debug.sf.showupdates", value, "0");
    mDebugRegion = atoi(value);

    property_get("debug.sf.ddms", value, "0");
    mDebugDDMS = atoi(value);
    if (mDebugDDMS) {
        if (!startDdmConnection()) {
            // start failed, and DDMS debugging not enabled
            mDebugDDMS = 0;
        }
    }
    ALOGI_IF(mDebugRegion, "showupdates enabled");
    ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
}

SurfaceFlinger类继承了BnSurfaceComposer类,而后者是一个实现了ISurfaceComposer接口的Binder本地对象类。 该对象被赋值给一个强指针引用flinger

当一个对象第一次被一个强指针引用时,该对象的成员函数onFirstRef就会被调用。下面来看SurfaceFlinger的成员函数onFirstRef

代码三:
// mEventQueue在SurfaceFlinger.h中声明
// these are thread safe
mutable MessageQueue mEventQueue;
// SurfaceFlinger.cpp中定义
void SurfaceFlinger::onFirstRef()
{
    mEventQueue.init(this);
}

MessageQueue 类在frameworks/native/services/surfaceflinger/MessageQueue.h中定义,init函数如下:

代码四:
void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
{
    mFlinger = flinger;
    mLooper = new Looper(true);
    mHandler = new Handler(*this);
}

调用MessageQueue的init,在MessageQueue中建了一个Looper和Handler,注意不是Java中的,native实现的。SurfaceFlinger的核心就是接收消息,处理消息。

执行init函数

回到代码一,继续往下执行init函数

void SurfaceFlinger::init() {
    ALOGI(  "SurfaceFlinger's main thread ready to run. "
            "Initializing graphics H/W...");

    status_t err;
    Mutex::Autolock _l(mStateLock);
    
    //初始化OpenGL 图形库相关配置
    // initialize EGL for the default display 将EGL初始化成默认的显示,默认是主屏幕,编号为0
    mEGLDisplay = 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));
            
    // get a RenderEngine for the given display / config (can't fail)
    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());

    // retrieve the EGL context that was selected/created
    mEGLContext = mRenderEngine->getEGLContext();

    LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
            "couldn't create EGLContext");

    // initialize our non-virtual displays
    //创建显示设备对象
    for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
        // set-up the displays that are already connected
        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
            // All non-virtual displays are currently considered secure.
            bool isSecure = true;
            createBuiltinDisplayLocked(type);
            wp<IBinder> token = mBuiltinDisplays[i];

            sp<IGraphicBufferProducer> producer;
            sp<IGraphicBufferConsumer> consumer;
            BufferQueue::createBufferQueue(&producer, &consumer,
                    new GraphicBufferAlloc());

            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i,
                    consumer);
            int32_t hwcId = allocateHwcDisplayId(type);
            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                    fbs, producer,
                    mRenderEngine->getEGLConfig());
            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 %zu as acquired/unblanked", i);
                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
            }
            mDisplays.add(token, hw);
        }
    }

    // make the GLContext current so that we can create textures when creating Layers
    // (which may happens before we render something)
    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);

    // start the EventThread
    //创建两个软件VSync,它们会根据硬件的VSync 来设置频率,稳定后,硬件VSync就会停止,使用软件生成的VSync
    //app的VSync信号,也就是Systrace中的VSync-app,它最终是发往到choreographer,主要处理三件事情INPUT、ANIMATION、TRAVERSAL
    sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            vsyncPhaseOffsetNs, true, "app");
    mEventThread = new EventThread(vsyncSrc);
    //SF的VSync信号,也就是Systrace中的VSync-sf,,它最终是发往到SurfaceFlinger,读取GraphicBuffer,最后通过Gralloc 把数据写入FrameBuffer
    sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
            sfVsyncPhaseOffsetNs, true, "sf");
    mSFEventThread = new EventThread(sfVsyncSrc);
    //SF的VSync信号控制逻辑也要放入mEventQueue消息队列
    mEventQueue.setEventThread(mSFEventThread);
    //VSync信号闸刀控制线程
    mEventControlThread = new EventControlThread(this);
    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);

    // set a fake vsync period if there is no HWComposer
    //如果硬件设备检测有问题,或者没有硬件设备驱动提供Vsync信号,则设置软件VSync信号
    if (mHwc->initCheck() != NO_ERROR) {
        mPrimaryDispSync.setPeriod(16666667);
    }

    // initialize our drawing state
    mDrawingState = mCurrentState;

    // set initial conditions (e.g. unblank default device)
    //初始化显示设备,调用initializeDisplays完成
    initializeDisplays();

    // start boot animation
    //启动开机动画,调用了startBootAnim函数,只是设置了两个属性,其中一个ctl.start是启动了bootanim进程
    startBootAnim();
}

关于VSync 信号,后面会详细讲解

SurfaceFlinger 的run函数

再次回到代码一,执行了flinger->run(),运行线程,等待数据。下面就来看看SurfaceFlinger 的run函数

void SurfaceFlinger::run() {
    do {
        waitForEvent();
    } while (true);
}

void SurfaceFlinger::waitForEvent() {
    mEventQueue.waitMessage();
}

调用了EventQueue的waitMessage方法,记住这里是在主线程中循环调用的。

void MessageQueue::waitMessage() {
    do {
        //flushCommands主要是清理工作的
        IPCThreadState::self()->flushCommands();
        //pollOnce是消息机制,主要调用了epoll_wait函数,会阻塞,阻塞完了会分发消息队列中的消息
        int32_t ret = mLooper->pollOnce(-1);
        switch (ret) {
            case Looper::POLL_WAKE:
            case Looper::POLL_CALLBACK:
                continue;
            case Looper::POLL_ERROR:
                ALOGE("Looper::POLL_ERROR");
            case Looper::POLL_TIMEOUT:
                // timeout (should not happen)
                continue;
            default:
                // should not happen
                ALOGE("Looper::pollOnce() returned unknown status %d", ret);
                continue;
        }
    } while (true);
}

发送消息

调用SurfaceFlinger 的postMessageSync(msg); 来发送消息

status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
        nsecs_t reltime, uint32_t /* flags */) {
    //向mEventQueue,即MessageQueue中发送消息
    status_t res = mEventQueue.postMessage(msg, reltime);
    //这里等着,同步就在同步函数中等着
    if (res == NO_ERROR) {
        msg->wait();
    }
    return res;
}

处理消息

从上面waitMessage得知,消息处理都位于里面无限循环处的的int32_t ret = mLooper->pollOnce(-1);我们追寻到Looper中的pollOnce函数,位于system/core/libutils/Looper.cpp中:

int Looper::pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outData) {
    int result = 0;
    for (;;) {
        ...
        result = pollInner(timeoutMillis);
    }
}

调用Looper 的函数 pollInner

int Looper::pollInner(int timeoutMillis) {
  // Invoke pending message callbacks.
    mNextMessageUptime = LLONG_MAX;
    while (mMessageEnvelopes.size() != 0) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
        const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);
        if (messageEnvelope.uptime <= now) {
            // Remove the envelope from the list.
            // We keep a strong reference to the handler until the call to handleMessage
            // finishes.  Then we drop it so that the handler can be deleted *before*
            // we reacquire our lock.
            { // obtain handler
                sp<MessageHandler> handler = messageEnvelope.handler;
                Message message = messageEnvelope.message;
                //把头删除啊
                mMessageEnvelopes.removeAt(0);
                mSendingMessage = true;
                mLock.unlock();

#if DEBUG_POLL_AND_WAKE || DEBUG_CALLBACKS
                ALOGD("%p ~ pollOnce - sending message: handler=%p, what=%d",
                        this, handler.get(), message.what);
#endif          
                //处理消息啊
                handler->handleMessage(message);
            } // release handler

            mLock.lock();
            mSendingMessage = false;
            result = ALOOPER_POLL_CALLBACK;
        } else {
            // The last message left at the head of the queue determines the next wakeup time.
            mNextMessageUptime = messageEnvelope.uptime;
            break;
        }
    }
}

发给SF的消息被封装在MessageEnvelope结构中,SF一直在mMessageEnvelopes队列中从头部取出消息,然后执行,即handler->handleMessage(message),这个即是我们上面提到的framework/native/services/surfaceflinger/MessageQueue.cpp中:

void MessageBase::handleMessage(const Message&) {
    this->handler();
    //打开栅栏
    barrier.open();
};

后面会以创建surface为例,来详细介绍SurfaceFlinger是如何 发送处理消息的

二、SurfaceFlinger的连接过程

每一个有UI的Android应用程序都需要与SurfaceFlinger服务建立一个连接,以便可以通过这个连接来请求SurfaceFlinger服务为它创建和渲染Surface。

应用程序和SurfaceFlinger服务 是运行在不同的进程中,所以在连接的过程中,涉及到很多进程间通信,主要联系可参考下图:

荐
                                                        Android 图形架构 之二—— SurfaceFlinger 启动和连接

在下面介绍的很多类,会使用类继承的接口来表示,下图是主要类关系,蓝色表示在客户端,紫色表示服务端
荐
                                                        Android 图形架构 之二—— SurfaceFlinger 启动和连接

当应用程序需要请求SurfaceFlinger服务时,首先需要构造SurfaceComposerClient对象,通过SurfaceComposerClient对象就可以访问SurfaceFlinger服务了。基本的服务流程都是这么走的,我们看一下SurfaceComposerClient的构造函数:

代码一:
SurfaceComposerClient::SurfaceComposerClient()
    : mStatus(NO_INIT), mComposer(Composer::getInstance())
{
}

SurfaceComposerClient 继承于RefBase类,在创建SurfaceComposerClient对象,系统第一次引用SurfaceComposerClient对象时,onFirstRef函数自动调用,我们看一下它的onFirstRef

代码二:
void SurfaceComposerClient::onFirstRef() {
   //1、获得SurfaceFlinger服务,从上图可知SurfaceFlinger 继承了ISurfaceComposer
    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
    if (sm != 0) {
        //2、与SurfaceFlinger建立连接
        sp<ISurfaceComposerClient> conn = sm->createConnection();
        if (conn != 0) {
            //之后就可以通过这个连接,进行通信
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

来看一下获取SurfaceFlinger服务的过程

代码三:
sp<ISurfaceComposer> ComposerService::getComposerService() {
    //ComposerService 是单例模式
    ComposerService& instance = ComposerService::getInstance();
    Mutex::Autolock _l(instance.mLock);
    if (instance.mComposerService == NULL) {
        //获取SurfaceFlinger服务的代理对象
        ComposerService::getInstance().connectLocked();
        assert(instance.mComposerService != NULL);
        ALOGD("ComposerService reconnected");
    }
    return instance.mComposerService;
}
代码四:
void ComposerService::connectLocked() {
    const String16 name("SurfaceFlinger");
    //获取SurfaceFlinger服务的代理对象,这里属于binder通信的代理对象获取过程,就不跟踪下去了
    //mComposerService中保存了 该代理对象 
    while (getService(name, &mComposerService) != NO_ERROR) {
        usleep(250000);
    }
    assert(mComposerService != NULL);                                                                                                         //省略了一些东西。。。
 
           }

这里我们回到代码一:sp<ISurfaceComposerClient> conn = sm->createConnection();

因为在代码一中,我们获取到的SurfaceFlinger服务的代理对象,是继承了BpSurfaceComposer,所以调用 sm->createConnection()会执行到下面的函数。

代码五:
class BpSurfaceComposer : public BpInterface<ISurfaceComposer>
{

...省略若干代码。。。

   
    virtual sp<ISurfaceComposerClient> createConnection()
    {
        Parcel data, reply;
        //写入数据
        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
        //发送进程通信的数据
        remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
        //等待服务端的进程通信返回后(就是代码六返回),才会执行下面的语句
        //进程通信的返回值reply.readStrongBinder()
        //interface_cast 该函数是为了获取binder通信中代理对象,通过它可获得binder实体对象 对应的binder代理对象
        return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
    }
...省略若干代码。。。
}

进程通信服务端的处理,也就是SurfaceFlinger服务 ,处理从客户端发来的CREATE_CONNECTION消息

代码六:
status_t BnSurfaceComposer::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case CREATE_CONNECTION: {
            CHECK_INTERFACE(ISurfaceComposer, data, reply);
            //createConnection 该函数的实现在SurfaceFlinger.cpp中
            sp<IBinder> b = IInterface::asBinder(createConnection());
            //把结果写入reply中,在客户端就会收到这个返回值,接着就会执行代码五的return 语句
            reply->writeStrongBinder(b);
            return NO_ERROR;
        }
    }
}        

接着,我们到SurfaceFlinger中看看createConnection的具体实现:


sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
    //创建Client,持有了SurfaceFlinger的强引用对象
    //接着调用了initClient,
    return initClient(new Client(this));
}
//进行一些检查,然后返回client,这里的client 是Binder实体对象,可以理解为服务端
static sp<ISurfaceComposerClient> initClient(const sp<Client>& client) {
    status_t err = client->initCheck();
    if (err == NO_ERROR) {
        return client;
    }
    return nullptr;
}

至此,建立连接的流程就分析完了,之后再应用程序端,就可以使用Client的Binder代理对象,与SurfaceFlinger进行通信了

拓展

在app端请求与SurfaceFlinger中创建连接时,在SurfaceFlinger会创建Client对象,每个app 对应一个Client
荐
                                                        Android 图形架构 之二—— SurfaceFlinger 启动和连接

上面在app端 拿到了Client的代理对象,之后可通过它来进行Binder 通信,但是注意,这个通信只是通知,具体内容的数据传输,使用的是匿名共享内存,因为UI的数据量很大,使用Binder通信效率低

荐
                                                        Android 图形架构 之二—— SurfaceFlinger 启动和连接
为了方便使用,将这块匿名共享内存 结构化为SharedClient

荐
                                                        Android 图形架构 之二—— SurfaceFlinger 启动和连接

荐
                                                        Android 图形架构 之二—— SurfaceFlinger 启动和连接

在每一个SharedClient里面,有至多31个SharedBufferStack。字面上来看,SharedBufferStack就是共享缓冲区堆栈。怎么理解呢?首先,Shared表明这个堆栈共享的。那么由谁来共享呢?当然就是Android应用程序和SurfaceFlinger服务了。其次,Buffer表明这个堆栈的内容是缓冲区。什么样的缓冲区呢?当然就是用来描述UI元数据的缓冲区了。再者,Stack表明用来描述UI元数据的缓冲区是需要按照一定的规则来访问的。综合起来,我们就可以认为每一个SharedBufferStack就是用来描述一系列需要按照一定规则来访问的缓冲区。

过去绘制UI的时候,都会采用一种称为“双缓冲”的技术。双缓冲意味着要使用两个缓冲区,其中一个称为Front Buffer,另外一个称为Back Buffer。UI总是先在Back Buffer中绘制,然后再和Front Buffer交换,渲染到显示设备中。SurfaceFlinger服务只不过是将传统的“双缓冲”技术升华和抽象为了一个SharedBufferStack。可别小看了这个升华和抽象,有了SharedBufferStack之后,SurfaceFlinger服务就可以使用N个缓冲区技术来绘制UI了。N值的取值范围为2到16。例如,在Android 2.3中,N的值等于2,而在Android 4.1中,据说就等于3了。

参考:
Android4.4深入浅出之SurfaceFlinger与Client通信框架(一)
Android 图形显示简述

Android SurfaceFlinger 学习之路(四)----SurfaceFlinger服务的启动与连接过程
概述和学习计划

本文地址:https://blog.csdn.net/xx326664162/article/details/108880222