Android4.4深入浅出之SurfaceFlinger框架-渲染一个surface(二)

SurfaceFlinger自启动之后,主要有三种类型线程参与工作:

1.binder线程,负责监控binder设备完成与客户端的交接

2.控制台事件监控线程,负责监控硬件帧缓冲区的睡眠/唤醒状态切换事件。

3.UI渲染线程,负责渲染UI。

一 UI渲染线程

UI渲染线程平时是处于休眠状态,一旦binder线程监测到有其他进程发过来的请求渲染UI的消息就会唤醒UI渲染线程,另一方面一旦SurfaceFlinger服务的控制台事件监控线程发现硬件帧缓冲区即将要进入睡眠或者唤醒状态时,它就会往SurfaceFlinger服务的UI渲染线程的消息队列中发送一个消息,以便SurfaceFlinger服务的UI渲染线程可以执行冻结或者解冻显示屏的操作。(摘自老罗的android之旅)接下来我从客户端一个请求渲染UI的请求入手开始研究渲染UI的整个过程

UI渲染线程的运行过程:

这里在说明一下,SurfaceFlinger的各个代理负责的事情:前面讲述的BpSurfaceComposer是SF在客户端的Binder代理,BnSurfaceComposer是本地对象负责和BpXXX交互,他们主要负责客户端请求连的整个过程和监控binder设备。而客户端与server端真正的交易则交给BpSurfaceComposerClient和BnSurfaceComposerClient来做,他们负责通知管理一个UI的渲染等重要过程。那我就从BpSurfaceComposerClient代理入手,还记得这个BpSurfaceComposerClient是哪里诞生的吗?在之前客户端请求连接到server的时候:

void SurfaceComposerClient::onFirstRef() {
    sp<ISurfaceComposer> sm(ComposerService::getComposerService());
    if (sm != 0) {
        sp<ISurfaceComposerClient> conn = sm->createConnection();
        if (conn != 0) {
            mClient = conn;
            mStatus = NO_ERROR;
        }
    }
}

当中的一句 mClient = conn;即把返回来的surfacecomposerclient保存了下来,又因为mClient是强指针,导致最终其实mClient就是BpSurfaceComposerClient类的对象,具体原因之前在研究SF启动过程中有详细说明。从连接之后,就获得了一个BpSurfaceComposerClient对象,这样连接后就可以进行下一步的渲染工作了。我们再看下BpSurfaceComposerClient这个类:

class BpSurfaceComposerClient : public BpInterface<ISurfaceComposerClient>
{
public:
    BpSurfaceComposerClient(const sp<IBinder>& impl)
        : BpInterface<ISurfaceComposerClient>(impl) {
    }

    virtual status_t createSurface(const String8& name, uint32_t w,
            uint32_t h, PixelFormat format, uint32_t flags,
            sp<IBinder>* handle,
            sp<IGraphicBufferProducer>* gbp) {
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
        data.writeString8(name);
        data.writeInt32(w);
        data.writeInt32(h);
        data.writeInt32(format);
        data.writeInt32(flags);
        remote()->transact(CREATE_SURFACE, data, &reply);
        *handle = reply.readStrongBinder();
        *gbp = interface_cast<IGraphicBufferProducer>(reply.readStrongBinder());
        return reply.readInt32();
    }

    virtual status_t destroySurface(const sp<IBinder>& handle) {
        Parcel data, reply;
        data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor());
        data.writeStrongBinder(handle);
        remote()->transact(DESTROY_SURFACE, data, &reply);
        return reply.readInt32();
    }
};

他有两个成员函数,分别是createSurface和destroySurface对应创建和销毁一个surface。两个核心函数的核心语句都在remote()->transact(CREATE_SURFACE, data, &reply);

即transact这个函数,之前也介绍过这是和binder设备打交道的必经之路。不做过多深入,这里意思就是简单的发个消息 CREATE_SURFACE给服务端,并把一个surface的信息打包成data一并发送过去。

server端这边会有线程监控binder设备,一旦收到消息自然调用对应的函数。这里就是BnSurfaceComposerClient负责了,不过这边跟之前的BnSurfaceComposer有点不一样,BnSurfaceComposerClient派生出一个Client类来负责这件事了,我们来看下这个类:

class Client : public BnSurfaceComposerClient
{
public:
        Client(const sp<SurfaceFlinger>& flinger);
        ~Client();

    status_t initCheck() const;

    // protected by SurfaceFlinger::mStateLock
    void attachLayer(const sp<IBinder>& handle, const sp<Layer>& layer);

    void detachLayer(const Layer* layer);

    sp<Layer> getLayerUser(const sp<IBinder>& handle) const;

private:
    // ISurfaceComposerClient interface
    virtual status_t createSurface(
            const String8& name,
            uint32_t w, uint32_t h,PixelFormat format, uint32_t flags,
            sp<IBinder>* handle,
            sp<IGraphicBufferProducer>* gbp);

    virtual status_t destroySurface(const sp<IBinder>& handle);

    virtual status_t onTransact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);

    // constant
    sp<SurfaceFlinger> mFlinger;

    // protected by mLock
    DefaultKeyedVector< wp<IBinder>, wp<Layer> > mLayers;

    // thread-safe
    mutable Mutex mLock;
};

其实核心的成员函数就两个 一个是createSurface和onTransact。首先看onTransact,毕竟他负责接收消息。

status_t Client::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // these must be checked
     IPCThreadState* ipc = IPCThreadState::self();
     const int pid = ipc->getCallingPid();
     const int uid = ipc->getCallingUid();
     const int self_pid = getpid();
     if (CC_UNLIKELY(pid != self_pid && uid != AID_GRAPHICS && uid != 0)) {
         // we're called from a different process, do the real check
         if (!PermissionCache::checkCallingPermission(sAccessSurfaceFlinger))
         {
             ALOGE("Permission Denial: "
                     "can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
             return PERMISSION_DENIED;
         }
     }
     return BnSurfaceComposerClient::onTransact(code, data, reply, flags);
}

这里前面的语句为了判断是否得到进入使用SF的权限,看他的返回 BnSurfaceComposerClient::onTransact(code, data, reply, flags);直接调用了另外一个onTransact接着看BnSurfaceComposerClient类中的onTransact

status_t BnSurfaceComposerClient::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
     switch(code) {
        case CREATE_SURFACE: {
            CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
            String8 name = data.readString8();
            uint32_t w = data.readInt32();
            uint32_t h = data.readInt32();
            PixelFormat format = data.readInt32();
            uint32_t flags = data.readInt32();
            sp<IBinder> handle;
            sp<IGraphicBufferProducer> gbp;
            status_t result = createSurface(name, w, h, format, flags,
                    &handle, &gbp);
            reply->writeStrongBinder(handle);
            reply->writeStrongBinder(gbp->asBinder());
            reply->writeInt32(result);
            return NO_ERROR;
        } break;
        case DESTROY_SURFACE: {
            CHECK_INTERFACE(ISurfaceComposerClient, data, reply);
            reply->writeInt32( destroySurface( data.readStrongBinder() ) );
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

这才是处理的核心中间人,还记得刚刚传的消息是CREATE_SURFACE,所以这里走第一个分支,首先解析数据包得到一些数据例如surface名字,长宽,还有格式等。然后在经过createSurface创建,但是到这里有个问题,这里的createSurface没有指明属于哪个类,发现去追踪起定义这追踪不到,这才想起这是调用了他子类Client的函数。我们回到之前client类中的createSurface;

status_t Client::createSurface(
        const String8& name,
        uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
        sp<IBinder>* handle,
        sp<IGraphicBufferProducer>* gbp)
{
    /*
     * createSurface must be called from the GL thread so that it can
     * have access to the GL context.
     */

    class MessageCreateLayer : public MessageBase {
        SurfaceFlinger* flinger;
        Client* client;
        sp<IBinder>* handle;
        sp<IGraphicBufferProducer>* gbp;
        status_t result;
        const String8& name;
        uint32_t w, h;
        PixelFormat format;
        uint32_t flags;
    public:
        MessageCreateLayer(SurfaceFlinger* flinger,
                const String8& name, Client* client,
                uint32_t w, uint32_t h, PixelFormat format, uint32_t flags,
                sp<IBinder>* handle,
                sp<IGraphicBufferProducer>* gbp)
            : flinger(flinger), client(client),
              handle(handle), gbp(gbp),
              name(name), w(w), h(h), format(format), flags(flags) {
        }
        status_t getResult() const { return result; }
        virtual bool handler() {
            result = flinger->createLayer(name, client, w, h, format, flags,
                    handle, gbp);
            return true;
        }
    };

    sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(),
            name, this, w, h, format, flags, handle, gbp);
    mFlinger->postMessageSync(msg);
    return static_cast<MessageCreateLayer*>( msg.get() )->getResult();
}

这个函数才真正的是程序进入SF领域的分水岭,函数内部定义了一个MessageCreateLayer类,我的理解是这个类把一个surface封装成了一个消息,这个消息当中含有surface的所有信息。sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(), name, this, w, h, format, flags, handle, gbp);定义了一个消息封装了surface,mFlinger->postMessageSync(msg);这个向SF发出一个异步信号,这个信号会唤醒SF处于休眠状态的UI渲染线程核心处理部分。

我们看下这个函数:

status_t SurfaceFlinger::postMessageSync(const sp<MessageBase>& msg,
        nsecs_t reltime, uint32_t flags) {
    status_t res = mEventQueue.postMessage(msg, reltime);
    if (res == NO_ERROR) {
        msg->wait();
    }
    return res;
}

调用postMessage()

status_t MessageQueue::postMessage(
        const sp<MessageBase>& messageHandler, nsecs_t relTime)
{
    const Message dummyMessage;
    if (relTime > 0) {
        mLooper->sendMessageDelayed(relTime, messageHandler, dummyMessage);
    } else {
        mLooper->sendMessage(messageHandler, dummyMessage);
    }
    return NO_ERROR;
}

这边 无论是sendMessageDelayed还是sendMessage都将会触发线程,将主线程(渲染UI)唤醒。那么我用一张图来介绍下主线程:

图画的很粗糙不过大致走向就是这样,当主线程收到消息后,就执行handleMessage。到这里可以去参考之前钱几篇SF流程系列文章看接下去是怎么渲染的。

Android4.4深入浅出之SurfaceFlinger框架-渲染一个surface(二)

时间: 2024-10-13 15:33:31

Android4.4深入浅出之SurfaceFlinger框架-渲染一个surface(二)的相关文章

Android4.4深入浅出之SurfaceFlinger总体结构

Android4.4 GUI系统框架之SurfaceFlinger 一.             Android GUI框架: SurfaceFlinger:每当用户程序刷新UI的时候,会中介BufferQueue申请一个buffer(dequeueBuffer),然后把UI的信息填入,丢给SurfaceFlinger,SurfaceFlinger通过计算多重计算合成visibleRegion之后,丢给openGL层处理,处理之后送到显示器display上显示. 根据整个Android系统的GU

Android应用程序请求SurfaceFlinger服务渲染Surface的过程分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7932268 在前面一篇文章中,我们分析了Android应用程序请求SurfaceFlinger服务创建Surface的过程.有了Surface之后,Android应用程序就可以在上面绘制自己的UI了,接着再请求SurfaceFlinger服务将这个已经绘制好了UI的Surface渲染到设备显示屏上去.在本文中,我们就将详细分析Android应用

android4.4 webview chromium实现硬件渲染的chromium内核结构

这里只关注与原生chromium不同的几个类. 一.DrawGLFunctor android4.4 webview chromium的硬件渲染是android ui系统和chromium内核协作 完成的.android ui系统负责触发网页渲染(调用WebView.onDraw()),以及提供 网页内容的最终目的地(HardwareCanvas);chromium内核提供具体的渲染行为. 这里就引出了DrawGLFunctor结构. DrawGLFunctor.java/draw_gl_fun

【SSH进阶之路】一步步重构容器实现Spring框架——从一个简单的容器开始(八)

目录 [SSH进阶之路]一步步重构容器实现Spring框架--从一个简单的容器开始(八) [SSH进阶之路]一步步重构容器实现Spring框架--解决容器对组件的"侵入式"管理的两种方案--主动查找和控制反转(九)(未更新) [SSH进阶之路]一步步重构容器实现Spring框架--配置文件+反射实现IoC容器(十)(未更新) [SSH进阶之路]一步步重构容器实现Spring框架--彻底封装,实现简单灵活的Spring框架(十一)(未更新) 最近一直在和容器打交道,甚至前面的博文,我们也

Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8079456 在前面的一系列文章中,我们学习了Android应用程序与SurfaceFlinger服务的关系,以及SurfaceFlinger服务的启动过程.初始化硬件帧缓冲区的过程.线程模型.SurfaceFlinger服务所做的一切都是为了给Android应用程序提服务的,即为Android应用程序渲染它们的UI.在本文中,我们就详细分析Su

jsWindow 对象 Window 对象 Window 对象表示浏览器中打开的窗口。 如果文档包含框架(frame 或 iframe 标签),浏览器会为 HTML 文档创建一个 window 对象,并为每个框架创建一个额外的 window 对象。 注释:没有应用于 window 对象的公开标准,不过所有浏览器都支持该对象。 Window 对象集合 集合 描述 frames[] 返回窗口中所有命

一.JSX简介 JSX就是Javascript和XML结合的一种格式.React发明了JSX,利用HTML语法来创建虚拟DOM.当遇到<,JSX就当HTML解析,遇到{就当JavaScript解析. 如下(JS写法) var child1 = React.createElement('li', null, 'First Text Content'); var child2 = React.createElement('li', null, 'Second Text Content'); var

【SSH进阶之路】一步步重构MVC实现Struts框架——从一个简单MVC开始(三)

目录: [SSH进阶之路]Struts基本原理 + 实现简单登录(二) [SSH进阶之路]一步步重构MVC实现Struts框架--从一个简单MVC开始(三) [SSH进阶之路]一步步重构MVC实现Struts框架--封装业务逻辑和跳转路径(四) [SSH进阶之路]一步步重构MVC实现Struts框架--彻底去掉逻辑判断(五) [SSH进阶之路]一步步重构MVC实现Struts框架--完善转向页面,大功告成(六) 上篇[SSH进阶之路]Struts基本原理 + 实现简单登录(二),我们介绍MVC和

Struts2应用框架出现一个高危漏洞

在jsp商城开发中通过采用JavaServlet/JSP技术,实现了基于Java EE Web应用的MVC设计模式的应用框架,是MVC经典设计模式中的一个经典产品,也是国际上应用最广泛的Web应用框架之一.java商城开发中的网上银行.政府网站.主要门户网站都大量使用Struts. 近日,Apache Struts2发布漏洞公告,声称Struts2应用框架出现一个高危漏洞.同时发布的,还有漏洞补丁包(最新版本为:2.3.15.1)和黑客攻击尝试验证代码. 经国内网站安全服务商SCANV.COM确

jQuery框架开发一个最简单的幻灯效果

在线演示 在这个课程中,我们将介绍如何使用jQuery来开发一个最简单的图片幻灯效果. 立刻观看互动课程:jQuery框架开发一个最简单的幻灯效果 阅读原文:jQuery框架开发一个最简单的幻灯效果 jQuery框架开发一个最简单的幻灯效果