当前位置: 移动技术网 > IT编程>开发语言>.net > 荐 Android 图形架构 之二—— SurfaceFlinger 启动和连接

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

2020年10月09日  | 移动技术网IT编程  | 我要评论
上一篇文章从全局来分析了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流程图,在这里插入图片描述

启动过程

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服务 是运行在不同的进程中,所以在连接的过程中,涉及到很多进程间通信,主要联系可参考下图:

在这里插入图片描述

在下面介绍的很多类,会使用类继承的接口来表示,下图是主要类关系,蓝色表示在客户端,紫色表示服务端
在这里插入图片描述

当应用程序需要请求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
在这里插入图片描述

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

在这里插入图片描述
为了方便使用,将这块匿名共享内存 结构化为SharedClient

在这里插入图片描述

在这里插入图片描述

在每一个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 图形显示简述


概述和学习计划

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

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网