精华内容
下载资源
问答
  • 大家都知道SurfaceFlinger安卓图形的引擎。安卓view的显示,OpenGL的显示必须通过SurfaceFlinger,才能显示到屏幕上。 按照常理,大部分开发者不喜欢文字,我也一样。另外,我也深知有些所谓的类图,把重点和非...

    大家都知道SurfaceFlinger是安卓图形的引擎。安卓view的显示,OpenGL的显示必须通过SurfaceFlinger,才能显示到屏幕上。

    按照常理,大部分开发者不喜欢文字,我也一样。另外,我也深知有些所谓的类图,把重点和非重点的东西喜欢放在一起,这不是我的风格。我只放重点东西,看下面这个简洁的类图。相信即使是初学者也能一看就懂。


    首先SurfaceFlinger是一个Bn,其次有一个MessageQueue。既然是Bn,那么有一个MessageQueue也就不足为怪了。另外包含了一个可以看到的LayerBase的数组。

     

    https://community.freescale.com/docs/DOC-93612

    • f2d0650a-5705-3eb3-b5aa-c4d71b8d7201-thumb.png
    • 大小: 24.9 KB
    • f69c19ff-9f54-3a23-aa97-1b7edf1d3c9d-thumb.png
    • 大小: 24.9 KB
    展开全文
  • 因此系统必须要有一个统一的管理者SurfaceFlinger SurfaceFlinger的任务 给app提供buffer 1.1、 通过gralloc模块向ashmen申请内存 1.2 、得到一个fd 1.3 、通过binder把fd传给某个app 1.4、 app再mmap('fd') app...

    假设现在有多个app1 2 3,如果它们随意访问fb,则屏幕显示必然是混乱不堪的。
    因此系统必须要有一个统一的管理者SurfaceFlinger

    SurfaceFlinger的任务

    • app提供buffer
      1.1、 通过gralloc模块向ashmen申请内存
      1.2 、得到一个fd
      1.3 、通过binderfd传给某个app
      1.4、 appmmap('fd')

    • app 1 2 3把各自界面发给它,它根据层次、大小进行合成,显示
      2.1、根据各个界面的z值(由WindowManagerService确定)决定前后顺序
      2.2、把这些排序后的buffer传给HardwareComposer

    • hwc不能处理(无hwc硬件、超出hwc层数)buffer时,使用图形库GL来处理

    在这里插入图片描述

    展开全文
  • 找到了mCore->mIsAbandoned = true 接下来分析consumerDisconnect是何时被调用,前面猜测是销毁surface(移除layer)的时候调用,接下来看下surfaceflinger移除layer流程 参考...

    学习android graphic很好的系列文章:https://blog.csdn.net/lewif/article/details/50526494
    GlSurfaceview和egl的相关文章 https://blog.csdn.net/qq_32175491/article/details/80271016
    https://blog.csdn.net/u012515661/article/details/55213460
    https://blog.csdn.net/kerwin_ch/article/details/48441247

    播放视频切换页面后返回发现surfaceview黑屏了,错误日志如下
    E/BufferQueueProducer: queueBuffer: BufferQueue has been abandoned

    看下日志来源

    //BufferQueueProducer.cpp
    status_t BufferQueueProducer::dequeueBuffer(int *outSlot,
            sp<android::Fence> *outFence, bool async,
            uint32_t width, uint32_t height, uint32_t format, uint32_t usage) {
        ATRACE_CALL();
        { // Autolock scope
            Mutex::Autolock lock(mCore->mMutex);
            mConsumerName = mCore->mConsumerName;
        } // Autolock scope
    
        BQ_LOGV("dequeueBuffer: async=%s w=%u h=%u format=%#x, usage=%#x",
                async ? "true" : "false", width, height, format, usage);
    
        if ((width && !height) || (!width && height)) {
            BQ_LOGE("dequeueBuffer: invalid size: w=%u h=%u", width, height);
            return BAD_VALUE;
        }
    
        status_t returnFlags = NO_ERROR;
        EGLDisplay eglDisplay = EGL_NO_DISPLAY;
        EGLSyncKHR eglFence = EGL_NO_SYNC_KHR;
        bool attachedByConsumer = false;
    
        { // Autolock scope
            Mutex::Autolock lock(mCore->mMutex);
            mCore->waitWhileAllocatingLocked();
    
            if (format == 0) {
                format = mCore->mDefaultBufferFormat;
            }
    
            // Enable the usage bits the consumer requested
            usage |= mCore->mConsumerUsageBits;
    
            int found;
            status_t status = waitForFreeSlotThenRelock("dequeueBuffer", async,
                    &found, &returnFlags);
            if (status != NO_ERROR) {
                return status;
            }
    
            // This should not happen
            if (found == BufferQueueCore::INVALID_BUFFER_SLOT) {
                BQ_LOGE("dequeueBuffer: no available buffer slots");
                return -EBUSY;
            }
    
            *outSlot = found;
            ATRACE_BUFFER_INDEX(found);
    
            attachedByConsumer = mSlots[found].mAttachedByConsumer;
    
            const bool useDefaultSize = !width && !height;
            if (useDefaultSize) {
                width = mCore->mDefaultWidth;
                height = mCore->mDefaultHeight;
            }
    
            mSlots[found].mBufferState = BufferSlot::DEQUEUED;
    
            const sp<GraphicBuffer>& buffer(mSlots[found].mGraphicBuffer);
            if ((buffer == NULL) ||
                    (static_cast<uint32_t>(buffer->width) != width) ||
                    (static_cast<uint32_t>(buffer->height) != height) ||
                    (static_cast<uint32_t>(buffer->format) != format) ||
                    ((static_cast<uint32_t>(buffer->usage) & usage) != usage))
            {
                mSlots[found].mAcquireCalled = false;
                mSlots[found].mGraphicBuffer = NULL;
                mSlots[found].mRequestBufferCalled = false;
                mSlots[found].mEglDisplay = EGL_NO_DISPLAY;
                mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
                mSlots[found].mFence = Fence::NO_FENCE;
    
                returnFlags |= BUFFER_NEEDS_REALLOCATION;
            }
    
            if (CC_UNLIKELY(mSlots[found].mFence == NULL)) {
                BQ_LOGE("dequeueBuffer: about to return a NULL fence - "
                        "slot=%d w=%d h=%d format=%u",
                        found, buffer->width, buffer->height, buffer->format);
            }
    
            eglDisplay = mSlots[found].mEglDisplay;
            eglFence = mSlots[found].mEglFence;
            *outFence = mSlots[found].mFence;
            mSlots[found].mEglFence = EGL_NO_SYNC_KHR;
            mSlots[found].mFence = Fence::NO_FENCE;
        } // Autolock scope
    
        if (returnFlags & BUFFER_NEEDS_REALLOCATION) {
            status_t error;
            BQ_LOGV("dequeueBuffer: allocating a new buffer for slot %d", *outSlot);
            sp<GraphicBuffer> graphicBuffer(mCore->mAllocator->createGraphicBuffer(
                        width, height, format, usage, &error));
            if (graphicBuffer == NULL) {
                BQ_LOGE("dequeueBuffer: createGraphicBuffer failed");
                return error;
            }
    
            { // Autolock scope
                Mutex::Autolock lock(mCore->mMutex);
    
                if (mCore->mIsAbandoned) {
                    BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
                    return NO_INIT;
                }
    
                mSlots[*outSlot].mFrameNumber = UINT32_MAX;
                mSlots[*outSlot].mGraphicBuffer = graphicBuffer;
            } // Autolock scope
        }
    
    
    //dequeue
    
          if (mCore->mIsAbandoned) {
                BQ_LOGE("dequeueBuffer: BufferQueue has been abandoned");
                return NO_INIT;
            }
    

    看看mCore->mIsAbandoned 是什么,机翻下

    // mIsAbandoned indicates that the BufferQueue will no longer be used to
    // consume image buffers pushed to it using the IGraphicBufferProducer
    // interface. It is initialized to false, and set to true in the
    // consumerDisconnect method. A BufferQueue that is abandoned will return
    // the NO_INIT error from all IGraphicBufferProducer methods capable of
    // returning an error.
    
    mIsAbandoned 指示 BufferQueue 将不再用于
    使用 IGraphicBufferProducerinterface将image buffers推送到BufferQueue 
    mIsAbandoned 被初始化为false,并在consumerDisconnect method中设置为真
    被丢弃的BufferQueue 会返回 NO_INIT error,这个错误来自可以返回返回 error
    的所有IGraphicBufferProducer methods
    bool mIsAbandoned;
    

    翻译不太了解,但是有关键的点 并在consumerDisconnect method中设置为真,就是说必须经过consumerDisconnect 才会设置为true。

    看下consumerDisconnect
    IGraphicBufferConsumer.h

      // consumerDisconnect disconnects a consumer from the BufferQueue. All
        // buffers will be freed and the BufferQueue is placed in the "abandoned"
        // state, causing most interactions with the BufferQueue by the producer to
        // fail.
        //
        // Return of a value other than NO_ERROR means an error has occurred:
        // * BAD_VALUE - no consumer is currently connected
    consumerDisconnect 将consumer 从缓冲队列中分离出来
    所有BufferQueue 将被释放,BufferQueue 被放置在“abandoned”状态中。
    导致生产者与BufferQueue 的大部分交互作用失败了。
    
    除了NO_ERROR 以外的值的返回意味着发生了一个错误:
     * BAD_VALUE - no消费者是当前连接 
        virtual status_t consumerDisconnect() = 0;
    

    注意“所有BufferQueue 将被释放”,我们知道创建surface过程就涉及到buferr的创建,那么buffer被释放时也应当是surface被销毁了。

    BufferQueueConsumer.h
    virtual status_t consumerDisconnect() { return disconnect(); }
    
    BufferQueueConsumer.cpp
    status_t BufferQueueConsumer::disconnect() {
        ATRACE_CALL();
    
        BQ_LOGV("disconnect(C)");
    
        Mutex::Autolock lock(mCore->mMutex);
    
        if (mCore->mConsumerListener == NULL) {
            BQ_LOGE("disconnect(C): no consumer is connected");
            return BAD_VALUE;
        }
    
    //找到了mIsAbandoned 
        mCore->mIsAbandoned = true;
        mCore->mConsumerListener = NULL;
        mCore->mQueue.clear();
        mCore->freeAllBuffersLocked();
        mCore->mDequeueCondition.broadcast();
        return NO_ERROR;
    }
    

    找到了mCore->mIsAbandoned = true 接下来分析consumerDisconnect是何时被调用,前面猜测是销毁surface(移除layer)的时候调用,接下来看下surfaceflinger移除layer流程
    参考https://blog.csdn.net/woai110120130/article/details/79112528

    
    void SurfaceFlinger::onMessageReceived(int32_t what) {
        ATRACE_CALL();
        switch (what) {
            case MessageQueue::TRANSACTION: {
                handleMessageTransaction();
                break;
            }
            case MessageQueue::INVALIDATE: {
           
                bool refreshNeeded = handleMessageTransaction();
                refreshNeeded |= handleMessageInvalidate();
                refreshNeeded |= mRepaintEverything;
                if (refreshNeeded) {
                    // Signal a refresh if a transaction modified the window state,
                    // a new buffer was latched, or if HWC has requested a full
                    // repaint
                    signalRefresh();
                }
                break;
            }
            case MessageQueue::REFRESH: {
                handleMessageRefresh();
                break;
            }
        }
    }
    
    bool SurfaceFlinger::handleMessageTransaction() {
        uint32_t transactionFlags = peekTransactionFlags(eTransactionMask);
        if (transactionFlags) {
            handleTransaction(transactionFlags);
            return true;
        }
        return false;
    }
    
    
    void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
    {
        ATRACE_CALL();
    
        // here we keep a copy of the drawing state (that is the state that's
        // going to be overwritten by handleTransactionLocked()) outside of
        // mStateLock so that the side-effects of the State assignment
        // don't happen with mStateLock held (which can cause deadlocks).
        State drawingState(mDrawingState);
    
        Mutex::Autolock _l(mStateLock);
        const nsecs_t now = systemTime();
        mDebugInTransaction = now;
    
        // Here we're guaranteed that some transaction flags are set
        // so we can call handleTransactionLocked() unconditionally.
        // We call getTransactionFlags(), which will also clear the flags,
        // with mStateLock held to guarantee that mCurrentState won't change
        // until the transaction is committed.
    
        transactionFlags = getTransactionFlags(eTransactionMask);
        handleTransactionLocked(transactionFlags);
    
        mLastTransactionTime = systemTime() - now;
        mDebugInTransaction = 0;
        invalidateHwcGeometry();
        // here the transaction has been committed
    }
    
    void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
    {
    //省略
        commitTransaction();
    
        updateCursorAsync();
    }
    
    void SurfaceFlinger::commitTransaction()
    {
        if (!mLayersPendingRemoval.isEmpty()) {
            // Notify removed layers now that they can't be drawn from
            for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) {
                mLayersPendingRemoval[i]->onRemoved();
            }
            mLayersPendingRemoval.clear();
        }
    
        // If this transaction is part of a window animation then the next frame
        // we composite should be considered an animation as well.
        mAnimCompositionPending = mAnimTransactionPending;
    
        mDrawingState = mCurrentState;
        mTransactionPending = false;
        mAnimTransactionPending = false;
        mTransactionCV.broadcast();
    }
    

    其实移除layer的点就在commitTransaction mLayersPendingRemoval[i]->onRemoved();调用Layer.cpp的OnRemoved

    void Layer::onRemoved() {
        mSurfaceFlingerConsumer->abandon();
    }
    

    //ConsumerBase.cpp

    void ConsumerBase::abandon() {
        CB_LOGV("abandon");
        Mutex::Autolock lock(mMutex);
    
        if (!mAbandoned) {
            abandonLocked();
            mAbandoned = true;
        }
    }
    
    void ConsumerBase::abandonLocked() {
    	CB_LOGV("abandonLocked");
        for (int i =0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
            freeBufferLocked(i);
        }
        // disconnect from the BufferQueue
        //发现consumerDisconnect
        mConsumer->consumerDisconnect();
        mConsumer.clear();
    }
    

    通过以上分析我们现在知道E/BufferQueueProducer: queueBuffer: BufferQueue has been abandoned这个日志的触发条件是
    1.app还在调用dequebuffer,即Mediaplayer还在作用。
    2.surface的销毁,layer的移除。

    那样解决方案很明了,在不使用视屏播放时必须把Mediaplayer和surface销毁,或者说surface销毁前Mediaplayer必须先销毁。

    展开全文
  • 文章转载至CSDN社区罗...前文在描述Android应用程序和SurfaceFlinger服务的关系时提到,每一个有UI的Android应用程序都需要与SurfaceFlinger服务建立一个连接,以便可以通过这个连接来请求SurfaceFlinger服务为它...

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7857163

    前文在描述Android应用程序和SurfaceFlinger服务的关系时提到,每一个有UIAndroid应用程序都需要与SurfaceFlinger服务建立一个连接,以便可以通过这个连接来请求SurfaceFlinger服务为它创建和渲染Surface。在本文中,我们将以Android系统的开机动画应用程序为例,详细描述Android应用程序是如何与SurfaceFlinger服务建立连接的。

            Android系统的开机动画是由应用程序bootanimation来实现的,它位于/system/bin目录下,它的具体实现可以参考Android系统的开机画面显示过程分析一文。为什么要选择Android系统的开机动画来分析Android应用程序与SurfaceFlinger服务的连接过程呢?首 先,负责实现开机动画的应用程序bootanimation也是一个Android应用程序,只不过它是使用C++语言来开发的;其次,应用程序 bootanimation是与UI相关的,即它与使用Java语言来开发的标准Android应用程序一样,都需要使用SurfaceFlinger服 务来创建和渲染自己的Surface,即开机动画;第三,由于应用程序bootanimation不涉及用户输入,即不需要与用户进行交互(触摸屏、键盘 等),因此它能够以最简洁的方式来体现Android应用程序与SurfaceFlinger服务的关系。

            从前面Android系统的开机画面显示过程分析一文可以知道,Android系统的开机动画是主要一个BootAnimation对象来实现,这个BootAnimation对象在构造的时候,会在内部创建一个SurfaceComposerClient对象来负责创建一个到SurfaceFlinger服务的连接。

            BootAnimation类的构造函数实现在文件frameworks/base/cmds/bootanimation/BootAnimation.cpp中,如下所示:

    1. BootAnimation::BootAnimation() : Thread(false)  
    2. {  
    3.     mSession = new SurfaceComposerClient();  
    4. }  

            mSession是BootAnimation类的成员变量,它是一个类型为SurfaceComposerClient的强指针,即sp<SurfaceComposerClient>。Android系统的智能指针的相关知识,可以参考Android系统的智能指针(轻量级指针、强指针和弱指针)的实现原理分析一文。

            在SurfaceComposerClient类内部,有一个类型为sp<ISurfaceComposerClient>的成员变量mClient,如图1所示:

    图1 SurfaceComposerClient的结构示意图

     

            SurfaceComposerClient类的成员变量mClient指向的实际上是一个类型为BpSurfaceComposerClient的 Binder代理对象,而这个类型为BpSurfaceComposerClient的Binder代理对象引用的是一个类型为Client的 Binder本地对象。在前面Android应用程序与SurfaceFlinger服务的关系概述和学习计划一文中提到,类型为Client的Binder本地对象是由SurfaceFlinger服务来负责创建的,并且运行在SurfaceFlinger服务中,用来代表使用SurfaceFlinger服务的一个客户端,即一个与UI相关的Android应用程序。

            由于Client类和BpSurfaceComposerClient类分别是一个Binder本地对象类和一个Binder代理对象类,它们都是根据 Android系统在应用程序框架层提供的Binder进程间通信库来实现的,它们的实现结构图分别如图2和图3所示:

    图2 Client类的实现结构图

    图3 BpSurfaceComposerClient类的实现结构图

            在图2和图3中,涉及到了比较多的Binder进程间通信库的类,需要读者对Android系统的Binder进程间通信机制有一定的理解和认识。在前面的Android进程间通信(IPC)机制Binder简要介绍和学习计划一系列文章,我们已经学习过Android系统的Binder进程间通信机制了,这里不再详述。
     
            图2和图3给我们最重要的信息是Client类和BpSurfaceComposerClient类均实现了类型为 ISurfaceComposerClient的Binder接口。ISurfaceComposerClient接口有两个重要的成员函数 getControlBlock和createSurface,它们定义在文件frameworks/base/include /surfaceflinger/ISurfaceComposerClient.h中,如下所示:
     
    1. class ISurfaceComposerClient : public IInterface  
    2. {  
    3. public:  
    4.     ......  
    5.   
    6.     virtual sp<IMemoryHeap> getControlBlock() const = 0;  
    7.     ......  
    8.   
    9.     /* 
    10.      * Requires ACCESS_SURFACE_FLINGER permission 
    11.      */  
    12.     virtual sp<ISurface> createSurface( surface_data_t* data,  
    13.                                         int pid,  
    14.                                         const String8& name,  
    15.                                         DisplayID display,  
    16.                                         uint32_t w,  
    17.                                         uint32_t h,  
    18.                                         PixelFormat format,  
    19.                                         uint32_t flags) = 0;  
    20.     ......  
    21.   
    22. };  
           其中,成员函数getControlBlock用来获得由SurfaceFlinger服务创建的一块用来传递UI元数据的匿名共享内存,而成员函数createSurface用来请求SurfaceFlinger服务创建一个Surface。从前面Android应用程序与SurfaceFlinger服务的关系概述和学习计划一 文可以知道,用来传递UI元数据的匿名共享内存最终会被结构化为一个SharedClient对象,这个SharedClient对象在每个应用程序进程 中至多存在一个。在接下来的两篇文章中,我们再详细分析ISurfaceComposerClient接口的成员函数getControlBlock和 createSurface的实现。
     
           理解了SurfaceComposerClient、Client以及BpSurfaceComposerClient这三个类的关系之后,接下来我们就 可以分析Android系统的开机动画应用程序bootanimation是如何与SurfaceFlinger服务建立连接的。
     
           从图1可以知道,SurfaceComposerClient类继承了RefBase类,因此,当BootAnimation类在构造函数创建了一个 SurfaceComposerClient对象,并且将这个对象赋值给类型为sp<SurfaceComposerClient>的智能指 针mSession时,就会导致SurfaceComposerClient类的成员函数onFirstRef被调用,而 SurfaceComposerClient类的成员函数onFirstRef在调用的过程中,就会在应用程序bootanimation与 SurfaceFlinger服务建立一个连接,这个过程如图4所示:
     
    图4 Android应用程序与SurfaceFlinger服务的连接过程
            接下来,我们就详细分析每一个步骤。
     
            Step 1. SurfaceComposerClient::onFirstRef
     
    1. void SurfaceComposerClient::onFirstRef()  
    2. {  
    3.     sp<ISurfaceComposer> sm(getComposerService());  
    4.     if (sm != 0) {  
    5.         sp<ISurfaceComposerClient> conn = sm->createConnection();  
    6.         if (conn != 0) {  
    7.             mClient = conn;  
    8.             ......  
    9.             mStatus = NO_ERROR;  
    10.         }  
    11.     }  
    12. }  
           SurfaceComposerClient类的成员函数onFirstRef实现在文件frameworks/base/libs/surfaceflinger_client/SurfaceComposerClient.cpp文件中。
     
           SurfaceComposerClient类的成员函数getComposerService用来获得SurfaceFlinger服务的一个代理接口,它的实现如下所示:
     
    1. sp<ISurfaceComposer> ComposerService::getComposerService() {  
    2.     return ComposerService::getInstance().mComposerService;  
    3. }  
            ComposerService类是单例模式,当我们第一次调用它的静态函数getInstance的时候,它就会在构造函数中获得SurfaceFlinger服务的一个代理接口,并且保存在它的成员变量mComposerService中,如下所示:
     
    1. ComposerService::ComposerService()  
    2. : Singleton<ComposerService>() {  
    3.     const String16 name("SurfaceFlinger");  
    4.     while (getService(name, &mComposerService) != NO_ERROR) {  
    5.         usleep(250000);  
    6.     }  
    7.     mServerCblkMemory = mComposerService->getCblk();  
    8.     mServerCblk = static_cast<surface_flinger_cblk_t volatile *>(  
    9.             mServerCblkMemory->getBase());  
    10. }  
           在ComposerService类的构造函数中,除了会获得SurfaceFlinger服务的代理接口之外,还会通过这个代理接口的成员函数 getCblk来获得一块匿名共享内存mServerCblkMemory。这块匿名共享内存是由SurfaceFlinger服务创建的,用来描述系统 显示屏的信息,例如,显示屏的个数、大小、方向、密度等等信息。由于这些信息可以通过一个surface_flinger_cblk_t对象来描述,因 此,ComposerService类的构造函数最后就将前面从SurfaceFlinger服务获得的一块匿名共享内存结构化为一个 surface_flinger_cblk_t对象,并且保存在ComposerService类的成员变量mServerCblk中。
     
           回到SurfaceComposerClient类的成员函数onFirstRef中,由于SurfaceFlinger服务实现了 ISurfaceComposer接口,因此,我们可以将前面获得的SurfaceFlinger服务的代理接口赋值给一个类型为 ISurfaceComposer的强指针sm,并且调用它的成员函数createConnection来请求SurfaceFlinger服务创建一个 连接,即创建一个类型为Client的Binder对象,并且将这个Binder对象的一个代理接口conn返回来。 SurfaceComposerClient类获得了SurfaceFlinger服务返回来的Client代理接口conn之后,就将它保存自己的成员 变量mClient中,这样开机动画应用程序bootanimation后续就可以通过它来请求SurfaceFlinger创建和渲染Surface 了。
     
           接下来,我们就继续分析SurfaceFlinger服务的成员函数createConnection的实现,以便可以了解它是如何为Android应用程序创建一个连接的。
     
           Step 2. SurfaceFlinger::createConnection
     
    1. sp<ISurfaceComposerClient> SurfaceFlinger::createConnection()  
    2. {  
    3.     sp<ISurfaceComposerClient> bclient;  
    4.     sp<Client> client(new Client(this));  
    5.     status_t err = client->initCheck();  
    6.     if (err == NO_ERROR) {  
    7.         bclient = client;  
    8.     }  
    9.     return bclient;  
    10. }  
            SurfaceFlinger类的成员函数createConnection实现在文件frameworks/base/services /surfaceflinger/SurfaceFlinger.cpp中,它的实现很简单,只是创建了一个类型为Client的Binder对象 client,并且获得它的一个ISurfaceComposerClient接口,最后将这个ISurfaceComposerClient接口,即一 个Client代理对象,返回给开机动画应用程序bootanimation。
     
            接下来,我们再继续分析Client对象的创建过程,,即Client类的构造函数的实现。
     
            Step 3. new Client
     
    1. Client::Client(const sp<SurfaceFlinger>& flinger)  
    2.     : mFlinger(flinger), mNameGenerator(1)  
    3. {  
    4. }  
            Client类有两个成员变量mFlinger和mNameGenerator,它们的类型分别为sp<SurfaceFlinger>和 int32_t,前者指向了SurfaceFlinger服务,而后者用来生成SurfaceFlinger服务为Android应用程序所创建的每一个 Surface的名称。例如,假设一个Android应用程序请求SurfaceFlinger创建了两个Surface,那么第一个Surface的名 称就由数字1来描述,而第二个Surface就由数字2来描述,依次类推。从前面Android应用程序与SurfaceFlinger服务的关系概述和学习计划这篇文章可以知道,一个Android应用程序最多可以创建31个Surface。
     
            回到SurfaceFlinger类的成员函数createConnection中,它将一个指向了一个Client对象的 ISurfaceComposerClient接口返回到开机动画应用程序bootanimation之后,开机动画应用程序bootanimation 就可以将它封装成一个类型为BpSurfaceComposerClient的Binder代理对象。
     
            Step 4. return BpSurfaceComposerClient
     
            类型为BpSurfaceComposerClient的Binder代理对象的封装过程实现在SurfaceFlinger服务的Binder代理对象类BpSurfaceComposer的成员函数createConnection中,如下所示:
     
    1. class BpSurfaceComposer : public BpInterface<ISurfaceComposer>  
    2. {  
    3. public:  
    4.     ......  
    5.   
    6.     virtual sp<ISurfaceComposerClient> createConnection()  
    7.     {  
    8.         uint32_t n;  
    9.         Parcel data, reply;  
    10.         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());  
    11.         remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);  
    12.         return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());  
    13.     }  
    14.   
    15.     ......  
    16. }  
            interface_cast是一个模板函数,它定义在framework/base/include/binder/IInterface.h文件中:
     
    1. template<typename INTERFACE>    
    2. inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)    
    3. {    
    4.     return INTERFACE::asInterface(obj);    
    5. }    
            从这里就可以看出,当模板参数为ISurfaceComposerClient的时候,模板函数interface_cast实际就是通过调用 ISurfaceComposerClient类的静态成员函数asInterface来将参数obj所描述的一个Binder代理对象,即一个 BpBinder对象,封装成一个BpSurfaceComposerClient对象。
     
            ISurfaceComposerClient类的静态成员函数asInterface是由frameworks/base/libs /surfaceflinger_client/ISurfaceComposerClient.cpp文件中的 IMPLEMENT_META_INTERFACE宏来定义的,如下所示:
     
    1. IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient");  
           
           IMPLEMENT_META_INTERFACE宏展开后,得到ISurfaceComposerClient类的静态成员函数asInterface的实现如下所示:
     
    1. android::sp<ISurfaceComposerClient> ISurfaceComposerClient::asInterface(const android::sp<android::IBinder>& obj)       {                                                                                         
    2.     android::sp<ISurfaceComposerClient> intr;                                                        
    3.         
    4.     if (obj != NULL) {                                                                         
    5.         intr = static_cast<ISurfaceComposerClient*>(                                                      
    6.                     obj->queryLocalInterface(ISurfaceComposerClient::descriptor).get());    
    7.             
    8.         if (intr == NULL) {                    
    9.             intr = new BpSurfaceComposerClient(obj);                                            
    10.         }                                              
    11.     }    
    12.     return intr;                                      
    13. }       
            参数obj是从BpSurfaceComposer类的成员函数createConnection传进来的,它指向的实际上是一个BpBinder对 象。当我们调用一个BpBinder对象的成员函数queryLocalInterface时,获得的是一个NULL指针,因 此,ISurfaceComposerClient类的静态成员函数asInterface最后就会将参数obj所指向的一个BpBinder对象封装成 一个BpSurfaceComposerClient对象,并且返回给调用者。

            BpSurfaceComposerClient对象的更具体封装过程可以参考前面浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路一文中所描述的BpServiceManager对象的封装过程。

            至此,开机动画应用程序bootanimation就通过SurfaceComposerClient类来与SurfaceFlinger服务建立一个连接了。
     
            在前面Android应用程序与SurfaceFlinger服务的关系概述和学习计划一文中提到,一个Android应用程序除了需要与SurfaceFlinger服务建立连接之外,还需要有一块用来传递UI元数据的匿名共享内存,即一个SharedClient对象,因此,在接下来的一篇文章中,我们就继续分析这块匿名共享内存的创建过程,敬请期待!
    老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!
    展开全文
  • 文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7884628 前面我们已经学习过Android应用程序与SurfaceFlinger服务的连接过程了。连接上SurfaceFlinger服务之后...
  • 文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8022957 在前面一篇文章中,我们简要介绍了Android系统Surface机制中的SurfaceFlinger服务。SurfaceFlinger...
  • 文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8062945 在前面两篇文章中,我们分析了SurfaceFlinger服务的启动过程以及SurfaceFlinger服务初始化硬件帧缓冲...
  • 文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8010977 前面我们从Android应用程序与SurfaceFlinger服务的关系出发,从侧面简单学习了SurfaceFlinger服务。有...
  • 文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7932268 在前面一篇文章中,我们分析了Android应用程序请求SurfaceFlinger服务创建Surface的过程。有了Surface...
  • 文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8079456 在前面的一系列文章中,我们学习了Android应用程序与SurfaceFlinger服务的关系,以及SurfaceFlinger...
  • 文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7846923 SurfaceFlinger服务负责绘制Android应用程序的UI,它的实现相当复杂,要从正面分析它的实现不是一件...
  • 文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8046659 在前文中,我们分析了SurfaceFlinger服务的启动过程。SurfaceFlinger服务在启动的过程中,会对系统的...

空空如也

空空如也

1 2 3 4
收藏数 61
精华内容 24
关键字:

安卓surfaceflinger