Android P 圖形顯示系統(tǒng)(六) SurfaceFlinger合成流程(一)

[TOC]

SurfaceFlinger合成流程(一)

通過(guò)前面的簡(jiǎn)單介紹,我們對(duì)HWC合成有大致的了解。下面我們根據(jù)實(shí)際代碼進(jìn)行講解。前面章節(jié),我們已經(jīng)說(shuō)過(guò),Layer的創(chuàng)建,和BufferQueue,那么Buffer進(jìn)入到BufferQueue隊(duì)列中后,怎么進(jìn)行合成顯示的呢?我們繼續(xù)來(lái)看。

Consumer端的FrameListener

你還記得Producer的frameAvailableListener嗎?Buffer放入隊(duì)列BufferQueue后,是不是通過(guò)frameAvailableListener->onFrameAvailable通知Consumer?大家可以再回望一下BufferQueueProducer::queueBuffer

frameAvailableListener是哪里來(lái)的?

我們先來(lái)看一下Consumer中Listener間的相互關(guān)系


消費(fèi)者Consumer中的Listener
  • BufferLayer有專門(mén)的Consumer,BufferLayerConsumer;BufferLayerConsumer繼承ConsumerBase。ConsumerBase通過(guò)IGraphicBufferConsumer和BufferQueue進(jìn)行通信的。
  • BufferQueue中的frameAvailableListener,是一個(gè)IConsumerListener的接口,對(duì)應(yīng)的Binder的Bn端實(shí)現(xiàn)為ProxyConsumerListener。
  • BufferLayer實(shí)現(xiàn)了ContentsChangedListener,ContentsChangedListener繼承FrameAvailableListener。BufferLayer的Listener實(shí)現(xiàn),被傳給了ConsumerBase。
  • ConsumerBase實(shí)現(xiàn)ConsumerListener接口,構(gòu)建ConsumerBase時(shí),會(huì)創(chuàng)建ProxyConsumerListener,將ConsumerBase實(shí)現(xiàn)的Listener接口傳給ProxyConsumerListener。
  • BufferQueue中Listener回調(diào)時(shí),會(huì)回調(diào)到ConsumerBase中。ConsumerBase中再通過(guò)BufferLayer實(shí)現(xiàn)的,傳下來(lái)的Listener回調(diào)到BufferLayer中。

層層回調(diào),別弄混淆了。

關(guān)鍵代碼:
BufferQueueProducer中通過(guò)frameAvailableListener->onFrameAvailable回調(diào)到ProxyConsumerListener中:

* frameworks/native/libs/gui/BufferQueue.cpp

void BufferQueue::ProxyConsumerListener::onFrameAvailable(
        const BufferItem& item) {
    sp<ConsumerListener> listener(mConsumerListener.promote());
    if (listener != NULL) {
        listener->onFrameAvailable(item);
    }
}

ProxyConsumerListener中的mConsumerListener是ConsumerBase中的實(shí)現(xiàn)。這里的listener->onFrameAvailable將回調(diào)到ConsumerBase中。

* frameworks/native/libs/gui/ConsumerBase.cpp

void ConsumerBase::onFrameAvailable(const BufferItem& item) {
    CB_LOGV("onFrameAvailable");

    sp<FrameAvailableListener> listener;
    { // scope for the lock
        Mutex::Autolock lock(mFrameAvailableMutex);
        listener = mFrameAvailableListener.promote();
    }

    if (listener != NULL) {
        CB_LOGV("actually calling onFrameAvailable");
        listener->onFrameAvailable(item);
    }
}

ConsumerBase中的mFrameAvailableListener是BufferLayer中的實(shí)現(xiàn):

* frameworks/native/services/surfaceflinger/BufferLayer.cpp

void BufferLayer::onFrameAvailable(const BufferItem& item) {
    // Add this buffer from our internal queue tracker
    { // Autolock scope
        Mutex::Autolock lock(mQueueItemLock);
        mFlinger->mInterceptor.saveBufferUpdate(this, item.mGraphicBuffer->getWidth(),
                                                item.mGraphicBuffer->getHeight(),
                                                item.mFrameNumber);
        // Reset the frame number tracker when we receive the first buffer after
        // a frame number reset
        if (item.mFrameNumber == 1) {
            mLastFrameNumberReceived = 0;
        }

        // Ensure that callbacks are handled in order
        while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
            status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
                                                               ms2ns(500));
            if (result != NO_ERROR) {
                ALOGE("[%s] Timed out waiting on callback", mName.string());
            }
        }

        mQueueItems.push_back(item);
        android_atomic_inc(&mQueuedFrames);

        // Wake up any pending callbacks
        mLastFrameNumberReceived = item.mFrameNumber;
        mQueueItemCondition.broadcast();
    }

    mFlinger->signalLayerUpdate();
}

BufferLayer中調(diào)用onFrameAvailable,去通知SurfaceFlinger進(jìn)行合成。

到這里,應(yīng)用端(Producer)生產(chǎn)完Buffer這件事,就通知到了SurfaceFlinger中了。

SurfaceFlinger的signalLayerUpdate,是通過(guò)MessageQueue來(lái)處理的,我們先來(lái)看看MessageQueue。

消息隊(duì)列MessageQueue

MessageQueue是SurfaceFlinger中的消息隊(duì)列,為什么需要消息隊(duì)列?我們應(yīng)用有一個(gè)主線程,專門(mén)進(jìn)行UI的處理。SurfaceFlinger同樣的,也有一個(gè)主線程,SurfaceFlinger的主線程主要進(jìn)行顯示數(shù)據(jù)的處理,也就是合成。

SurfaceFlinger中,mEventQueue是MessageQueue的一個(gè)棧對(duì)象,采用mutable修飾。SurfaceFlinger在初次引用時(shí),會(huì)對(duì)mEventQueue進(jìn)行初始化。

* frameworks/native/services/surfaceflinger/MessageQueue.cpp

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

MessageQueue初始化時(shí),創(chuàng)建了一個(gè)Looper和一個(gè)Handler。

此外,在SurfaceFlinger初始化時(shí),創(chuàng)建了一個(gè)EventThread,并傳給了MessageQueue。

void SurfaceFlinger::init() {
    ... ...
    sp<VSyncSource> sfVsyncSrc =
            new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
    mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
    mEventQueue.setEventThread(mSFEventThread);

MessageQueue的setEventThread函數(shù)如下:

void MessageQueue::setEventThread(const sp<EventThread>& eventThread)
{
    if (mEventThread == eventThread) {
        return;
    }

    if (mEventTube.getFd() >= 0) {
        mLooper->removeFd(mEventTube.getFd());
    }

    mEventThread = eventThread;
    mEvents = eventThread->createEventConnection();
    mEvents->stealReceiveChannel(&mEventTube);
    mLooper->addFd(mEventTube.getFd(), 0, Looper::EVENT_INPUT,
            MessageQueue::cb_eventReceiver, this);
}

MessageQueue在setEventThread時(shí),主要做以下幾件事:

  • 創(chuàng)建一個(gè)BitTube對(duì)象mEventTube

  • 創(chuàng)建一個(gè)EventConnection

sp<EventThread::Connection> EventThread::createEventConnection() const {
    return new Connection(const_cast<EventThread*>(this));
}

Connection在第一次引用時(shí),將會(huì)被注冊(cè)到mEventThread中。

void EventThread::Connection::onFirstRef() {
    // NOTE: mEventThread doesn't hold a strong reference on us
    mEventThread->registerDisplayEventConnection(this);
}

在注冊(cè)時(shí),Connection將會(huì)被添加到mDisplayEventConnections 中。

status_t EventThread::registerDisplayEventConnection(
        const sp<EventThread::Connection>& connection) {
    Mutex::Autolock _l(mLock);
    mDisplayEventConnections.add(connection);
    mCondition.broadcast();
    return NO_ERROR;
}

mDisplayEventConnections是一個(gè)已經(jīng)注冊(cè)的Connection的集合。

  • 將mEventTube和EventConnection關(guān)聯(lián)
status_t EventThread::Connection::stealReceiveChannel(gui::BitTube* outChannel) {
    outChannel->setReceiveFd(mChannel.moveReceiveFd());
    return NO_ERROR;
}

Connection創(chuàng)建時(shí),將默認(rèn)創(chuàng)建一個(gè)4k的BitTube,BitTube封裝的是一對(duì)socket,一個(gè)發(fā)送,一個(gè)接收,可傳輸?shù)腂uffer大小為4K。

void BitTube::init(size_t rcvbuf, size_t sndbuf) {
    int sockets[2];
    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
        size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
        // since we don't use the "return channel", we keep it small...
        setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
        setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
        fcntl(sockets[0], F_SETFL, O_NONBLOCK);
        fcntl(sockets[1], F_SETFL, O_NONBLOCK);
        mReceiveFd.reset(sockets[0]);
        mSendFd.reset(sockets[1]);
    } else {
        mReceiveFd.reset();
        ALOGE("BitTube: pipe creation failed (%s)", strerror(errno));
    }
}

MessageQueue中的mEventTube,和mReceiveFd關(guān)聯(lián)。

  • addFd函數(shù),將fd添加到MessageQueue的Looper中。
    注意,Looper的callback為MessageQueue::cb_eventReceiver,data為MessageQueue本身。
int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
    MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
    return queue->eventReceiver(fd, events);
}

回到SurfaceFlinger的signalLayerUpdate函數(shù):

void SurfaceFlinger::signalLayerUpdate() {
    mEventQueue.invalidate();
}

signalLayerUpdate中,調(diào)用MQ的invalidate。

void MessageQueue::invalidate() {
    mEvents->requestNextVsync();
}

MQ的invalidate的函數(shù),將請(qǐng)求下一個(gè)Vsync。Vsync是一種同步機(jī)制,垂直同步,我們可以理解為SurfaceFlinger的工作節(jié)拍。

void EventThread::requestNextVsync(
        const sp<EventThread::Connection>& connection) {
    Mutex::Autolock _l(mLock);

    mFlinger.resyncWithRateLimit();

    if (connection->count < 0) {
        connection->count = 0;
        mCondition.broadcast();
    }
}

注意這里的count >= 0。

EventThread就是一個(gè)事件分發(fā)的線程,第一次引用時(shí),線程啟動(dòng)。

void EventThread::onFirstRef() {
    run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}

EventThread的threadLoop函數(shù)體如下:

bool EventThread::threadLoop() {
    DisplayEventReceiver::Event event;
    Vector< sp<EventThread::Connection> > signalConnections;
    signalConnections = waitForEvent(&event);

    // dispatch events to listeners...
    const size_t count = signalConnections.size();
    for (size_t i=0 ; i<count ; i++) {
        const sp<Connection>& conn(signalConnections[i]);
        // now see if we still need to report this event
        status_t err = conn->postEvent(event);
        if (err == -EAGAIN || err == -EWOULDBLOCK) {
            ... ...
            ALOGW("EventThread: dropping event (%08x) for connection %p",
                    event.header.type, conn.get());
        } else if (err < 0) {
            removeDisplayEventConnection(signalConnections[i]);
        }
    }
    return true;
}

waitForEvent,等待事件Event。看看哪些Connection是被觸發(fā)的,對(duì)于被觸發(fā)的Connection,signalConnections,通過(guò)postEvent將事件Event分發(fā)出去。

Event這邊的控制邏輯,基本都在waitForEvent中。waitForEvent中,采用while循環(huán),條件是signalConnections為空。EventThread中主要控制兩事件,Vsync事件和顯示屏的HotPlug熱插拔事件

    enum {
        DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'),
        DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),
    };

我們分段來(lái)看:

Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
        DisplayEventReceiver::Event* event)
{
    Mutex::Autolock _l(mLock);
    Vector< sp<EventThread::Connection> > signalConnections;

    do {
        bool eventPending = false;
        bool waitForVSync = false;

        size_t vsyncCount = 0;
        nsecs_t timestamp = 0;
        for (int32_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
            timestamp = mVSyncEvent[i].header.timestamp;
            if (timestamp) {
                // 有一個(gè)Vsync事件要分發(fā)
                if (mInterceptVSyncs) {
                    mFlinger.mInterceptor.saveVSyncEvent(timestamp);
                }
                *event = mVSyncEvent[i];
                mVSyncEvent[i].header.timestamp = 0;
                vsyncCount = mVSyncEvent[i].vsync.count;
                break;
            }
        }

看看有沒(méi)有Vsync事件要分發(fā),timestamp不為0,表示有Vync事件要分發(fā)。

        if (!timestamp) {
            // no vsync event, see if there are some other event
            eventPending = !mPendingEvents.isEmpty();
            if (eventPending) {
                // we have some other event to dispatch
                *event = mPendingEvents[0];
                mPendingEvents.removeAt(0);
            }
        }

mPendingEvents,這里主要是是HotPlug事件。

找出在等待事件的Connection:

        size_t count = mDisplayEventConnections.size();
        for (size_t i=0 ; i<count ; ) {
            sp<Connection> connection(mDisplayEventConnections[i].promote());
            if (connection != NULL) {
                bool added = false;
                if (connection->count >= 0) {
                    // 需要Vsync,至少有一個(gè)Connection的count >= 0。
                    waitForVSync = true;
                    if (timestamp) {
                        // we consume the event only if it's time
                        // (ie: we received a vsync event)
                        if (connection->count == 0) {
                            // fired this time around
                            connection->count = -1;
                            signalConnections.add(connection);
                            added = true;
                        } else if (connection->count == 1 ||
                                (vsyncCount % connection->count) == 0) {
                            // continuous event, and time to report it
                            signalConnections.add(connection);
                            added = true;
                        }
                    }
                }

                if (eventPending && !timestamp && !added) {
                    // 沒(méi)有Vsync事件要處理,但是有其他的事件要處理
                    signalConnections.add(connection);
                }
                ++i;
            } else {
                // Connection不存在了
                mDisplayEventConnections.removeAt(i);
                --count;
            }
        }

Connection的count >= 0表示需要Vsync。eventPending && !timestamp && !added表示沒(méi)有Vsync事件要處理,但是有其他的事件要處理。

        if (timestamp && !waitForVSync) {
            disableVSyncLocked();
        } else if (!timestamp && waitForVSync) {
            enableVSyncLocked();
        }

timestamp && !waitForVSync如果有Vsync事件要分發(fā),但是又沒(méi)有Connection需要Vsync事件時(shí),把Vsync給關(guān)掉。相反,如果有Connection需要Vsync,而此時(shí)又沒(méi)有Vsync事件時(shí),需要將Vsync打開(kāi)。

        if (!timestamp && !eventPending) {
            if (waitForVSync) {
                bool softwareSync = mUseSoftwareVSync;
                nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000);
                if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) {
                    if (!softwareSync) {
                        ALOGW("Timed out waiting for hw vsync; faking it");
                    }
                    // FIXME: how do we decide which display id the fake
                    // vsync came from ?
                    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
                    mVSyncEvent[0].header.id = DisplayDevice::DISPLAY_PRIMARY;
                    mVSyncEvent[0].header.timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
                    mVSyncEvent[0].vsync.count++;
                }
            } else {
                mCondition.wait(mLock);
            }
        }
    } while (signalConnections.isEmpty());

    return signalConnections;
}

如果此時(shí)沒(méi)有Vsync事件,或其他的Event事件,那就處于等待中。如果是等待Vsync,那么通過(guò)mCondition.waitRelative進(jìn)行等待,如果是硬件Vsync還不能用或者出現(xiàn)問(wèn)題時(shí),設(shè)置一個(gè)超時(shí)時(shí)間,進(jìn)行屏幕的喚醒。
如果Connection需要Vsync,那么就進(jìn)程sleep。

Vsync事件到來(lái)時(shí),將回調(diào)到onVSyncEvent:

void EventThread::onVSyncEvent(nsecs_t timestamp) {
    Mutex::Autolock _l(mLock);
    mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
    mVSyncEvent[0].header.id = 0;
    mVSyncEvent[0].header.timestamp = timestamp;
    mVSyncEvent[0].vsync.count++;
    mCondition.broadcast();
}

Hotplug事件到來(lái)時(shí),將回調(diào)到onHotplugReceived:

void EventThread::onHotplugReceived(int type, bool connected) {
    ALOGE_IF(type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES,
            "received hotplug event for an invalid display (id=%d)", type);

    Mutex::Autolock _l(mLock);
    if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
        DisplayEventReceiver::Event event;
        event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG;
        event.header.id = type;
        event.header.timestamp = systemTime();
        event.hotplug.connected = connected;
        mPendingEvents.add(event);
        mCondition.broadcast();
    }
}

注意,Event事件哪兒回調(diào)回來(lái)的我們先不管,我們先記住這里的邏輯。

Vsync事件是跟屏幕的刷新頻率有關(guān),比如60Hz的屏幕,兩個(gè)Vsync事件間的時(shí)間為1/60s,也就是16.67ms左右。SurfaceFlinger每隔16.67ms進(jìn)行一次合成,顯示。

另外,需要注意的是,SurfaceFlinger和App的EventThread是分開(kāi)的,不是同一個(gè)。

void SurfaceFlinger::init() {
    ... ...

    // start the EventThread
    sp<VSyncSource> vsyncSrc =
            new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
    mEventThread = new EventThread(vsyncSrc, *this, false);
    sp<VSyncSource> sfVsyncSrc =
            new DispSyncSource(&mPrimaryDispSync, SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
    mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
    mEventQueue.setEventThread(mSFEventThread);

回到MessageQueue,Connection通過(guò)postEvent將Event拋出來(lái)后,通過(guò)sendEvents將事件發(fā)出去。

status_t EventThread::Connection::postEvent(
        const DisplayEventReceiver::Event& event) {
    ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
    return size < 0 ? status_t(size) : status_t(NO_ERROR);
}

DisplayEventReceiver中是通過(guò)BitTube將事件發(fā)出去,sendObjects注意這里的參數(shù)。

ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
        Event const* events, size_t count)
{
    return gui::BitTube::sendObjects(dataChannel, events, count);
}

數(shù)據(jù)是什么地方接受的呢?回到SurfaceFlinger

SurfaceFlinger線程run時(shí),啟動(dòng)一個(gè)死循環(huán),循環(huán)等待事件。

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

waitForEvent中,調(diào)用MessageQueue的waitMessage函數(shù):

void MessageQueue::waitMessage() {
    do {
        IPCThreadState::self()->flushCommands();
        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");
                continue;
            case Looper::POLL_TIMEOUT:
                // timeout (should not happen)
                continue;
            default:
                // should not happen
                ALOGE("Looper::pollOnce() returned unknown status %d", ret);
                continue;
        }
    } while (true);
}

waitMessage,通過(guò)采用一個(gè)死循環(huán),處理Looper的pollOnce。Looper內(nèi)部的邏輯就不看了,主要是采用epoll_wait對(duì)fd進(jìn)行監(jiān)聽(tīng),BitTube發(fā)送Event對(duì)象后,epoll_wait結(jié)束,調(diào)用callback,處理事件

int callbackResult = response.request.callback->handleEvent(fd, events, data);

MessageQueue對(duì)應(yīng)的callback為cb_eventReceiver:

int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
    MessageQueue* queue = reinterpret_cast<MessageQueue *>(data);
    return queue->eventReceiver(fd, events);
}

eventReceiver,處理事件:

int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
    ssize_t n;
    DisplayEventReceiver::Event buffer[8];
    while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
        for (int i=0 ; i<n ; i++) {
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                mHandler->dispatchInvalidate();
                break;
            }
        }
    }
    return 1;
}

dispatchInvalidate,封裝為MessageQueue::INVALIDATE

void MessageQueue::Handler::dispatchInvalidate() {
    if ((android_atomic_or(eventMaskInvalidate, &mEventMask) & eventMaskInvalidate) == 0) {
        mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE));
    }
}

MessageQueue中,兩種Message,INVALIDATEREFRESH

    enum {
        INVALIDATE  = 0,
        REFRESH     = 1,
    };

Message的分發(fā)略過(guò),Handler對(duì)Message的處理如下:

void MessageQueue::Handler::handleMessage(const Message& message) {
    switch (message.what) {
        case INVALIDATE:
            android_atomic_and(~eventMaskInvalidate, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
        case REFRESH:
            android_atomic_and(~eventMaskRefresh, &mEventMask);
            mQueue.mFlinger->onMessageReceived(message.what);
            break;
    }
}

收到消息后,再調(diào)回SurfaceFlinger在onMessageReceived中處理。

再看SurfaceFlinger的處理之前,我們先稍微整理一下MessageQueue,MessageQueue的類圖如下:


MessageQueue的類圖

顯示設(shè)備DispalyDevice

SurfaceFlinger中,每個(gè)顯示屏我們用DisplayDevice進(jìn)行描述,它除了描述了Display的信息,還包括很多和合成相關(guān)的邏輯。相比于native層,Display信息是在Android的Framework層管理的,提供了專門(mén)的服務(wù)DisplayManagerService(DMS),DMS后續(xù)再介紹。

Display接口服務(wù)

。從Android 8.0開(kāi)始,Vsync和hotplug的接收接口IDisplayEventReceiver作為一個(gè)單獨(dú)的庫(kù)從SurfaceFlinger中獨(dú)立出來(lái),設(shè)計(jì)為3層模式,JAVA層,Native層和HAL層。編譯為libdisplayservicehidl庫(kù),代碼在如下位置:

frameworks/native/services/displayservice

Display 接口 Android.bp如下:

cc_library_shared {
    name: "libdisplayservicehidl",

    srcs: [
        "DisplayService.cpp",
        "DisplayEventReceiver.cpp",
    ],

    shared_libs: [
        "libbase",
        "liblog",
        "libgui",
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "android.frameworks.displayservice@1.0",
    ],

    export_include_dirs: ["include"],
    export_shared_lib_headers: [
        "android.frameworks.displayservice@1.0",
        "libgui",
        "libutils",
    ],

    cflags: [
        "-Werror",
        "-Wall",
    ]
}

hal層也抽象出Display的單獨(dú)模塊displayservice。代碼為在:

frameworks/hardware/interfaces/displayservice

displayservice的Android.bp如下:

hidl_interface {
    name: "android.frameworks.displayservice@1.0",
    root: "android.frameworks",
    vndk: {
        enabled: true,
    },
    srcs: [
        "types.hal",
        "IDisplayEventReceiver.hal",
        "IDisplayService.hal",
        "IEventCallback.hal",
    ],
    interfaces: [
        "android.hidl.base@1.0",
    ],
    types: [
        "Status",
    ],
    gen_java: true,
}

displayservice還比較簡(jiǎn)單,沒(méi)有太多接口:

  • types中只定義了一個(gè)狀態(tài)
* frameworks/hardware/interfaces/displayservice/1.0/types.hal

package android.frameworks.displayservice@1.0;

enum Status : uint32_t {
    SUCCESS,
    BAD_VALUE,
    UNKNOWN,
};
  • IDisplayEventReceiver.hal中定義了Receiver的接口
package android.frameworks.displayservice@1.0;

import IEventCallback;

interface IDisplayEventReceiver {
    /**
     * 添加callback,開(kāi)始接收Events事件,熱插拔是默認(rèn)打開(kāi)的,Vysnc需要通過(guò)setVsyncRate打開(kāi)
     */
    init(IEventCallback callback) generates (Status status);

    /**
     * 開(kāi)始或停止發(fā)送callback
     */
    setVsyncRate(int32_t count) generates (Status status);

    /**
     * 請(qǐng)求一個(gè)Vsync,如果setVsyncRate是0,這不起作用
     */
    requestNextVsync() generates (Status status);

    /**
     * Server端丟棄所以的callback,停止發(fā)送
     */
    close() generates (Status status);
};
  • IDisplayService.hal
package android.frameworks.displayservice@1.0;

import IDisplayEventReceiver;

interface IDisplayService {
    /**
     * 創(chuàng)建新的receiver.
     */
    getEventReceiver() generates(IDisplayEventReceiver receiver);
};
  • IEventCallback.hal
package android.frameworks.displayservice@1.0;

interface IEventCallback {
    /**
     * Vsync事件
     */
    oneway onVsync(uint64_t timestamp, uint32_t count);

    /**
     * hotplug事件
     */
    oneway onHotplug(uint64_t timestamp, bool connected);
};

displayservice的接口,主要是提供給Vendor的HAL使用,讓Vendor的HAL也能夠接收Vsync數(shù)據(jù)。libdisplayservicehidl中也主要是DisplayEventReceiver。所以,這里的IDisplayEventReceiver接口 這么設(shè)計(jì)的 主要是提供給Vendor用。

顯示屏的類型

顯示屏幕什么時(shí)候創(chuàng)建?各類型的顯示屏不一樣,Android支持3中類型的顯示屏:主顯外顯虛顯

* frameworks/native/services/surfaceflinger/DisplayDevice.h

    enum DisplayType {
        DISPLAY_ID_INVALID = -1,
        DISPLAY_PRIMARY     = HWC_DISPLAY_PRIMARY,
        DISPLAY_EXTERNAL    = HWC_DISPLAY_EXTERNAL,
        DISPLAY_VIRTUAL     = HWC_DISPLAY_VIRTUAL,
        NUM_BUILTIN_DISPLAY_TYPES = HWC_NUM_PHYSICAL_DISPLAY_TYPES,
    };

主顯示屏幕和外顯,都采用熱插拔的形式,連接斷開(kāi)時(shí)從底層驅(qū)動(dòng)上報(bào)熱插拔事件,這是在EventThread中處理的。

  • 主顯示屏 DISPLAY_PRIMARY
    主顯示屏幕默認(rèn)是必現(xiàn)支持的,也就是說(shuō),開(kāi)機(jī)時(shí)就應(yīng)該上報(bào) * 連接* 事件,知道屏幕關(guān)閉時(shí),才斷開(kāi)。這里說(shuō)的屏幕關(guān)閉是真正的關(guān)閉,休眠,鎖屏等狀態(tài)屏幕還是開(kāi)著的。基本也就是關(guān)機(jī)的時(shí)候。

  • 外顯示屏 DISPLAY_EXTERNAL
    外顯示屏幕,一般是有線連接的屏幕,比如HDMI,MHL或者是其他連接標(biāo)準(zhǔn)連接的屏幕,外顯一般經(jīng)常進(jìn)行熱插拔。

  • 虛擬顯示屏 DISPLAY_VIRTUAL
    虛擬顯示屏,也就是說(shuō)這個(gè)顯示屏是不存在物理設(shè)備的,是個(gè)虛擬的。

我們先看看DisplayDevice相關(guān)類之間的關(guān)系:


DisplayDevice和Surface相關(guān)的類圖

我們可以這么來(lái)理解:

  • Android支持多個(gè)顯示屏幕,每一個(gè)顯示屏幕用DisplayDevice進(jìn)行描述,SurfaceFlinger中有這些顯示屏的信息即mDisplay
  • 每個(gè)顯示屏幕,都一個(gè)相關(guān)聯(lián)的Buffer,這個(gè)Buffer用 DisplaySurface進(jìn)行描述。
  • 每種類型的顯示屏,具體采用的Buffer不盡相同,主屏和外顯采用FramebufferSurface,而虛擬顯示屏采用VirtualDisplaySurface。
  • DisplaySurface有自己的BufferQueue,都繼承ConsumerBase,所以這里DisplaySurface比較特殊,都是消費(fèi)者。VirtualDisplaySurface更猛,它還繼承BnGraphicBufferProducer,也是生產(chǎn)者。
  • RE_Surface是RE命名空間的Surface,和BufferQueue中的Surface同名,但是作用不一樣。主要是給RenderEngine用,RenderEngine是一個(gè)抽象類,渲染引擎,用于Client端的合成,一般用OpenGL進(jìn)程合成。

DisplayDevice的熱插拔處理

SurfaceFlinger在初始化的時(shí)候,注冊(cè)Callback接口后。顯示屏幕插上和斷開(kāi)時(shí),將通過(guò)HAL回調(diào)回來(lái)。HAL回調(diào)的過(guò)程先不關(guān)注,從SurfaceFlinger中開(kāi)始看。

void SurfaceFlinger::onHotplugReceived(int32_t sequenceId,
        hwc2_display_t display, HWC2::Connection connection,
        bool primaryDisplay) {
    ALOGV("onHotplugReceived(%d, %" PRIu64 ", %s, %s)",
          sequenceId, display,
          connection == HWC2::Connection::Connected ?
                  "connected" : "disconnected",
          primaryDisplay ? "primary" : "external");

    ConditionalLock lock(mStateLock,
            std::this_thread::get_id() != mMainThreadId);

    if (primaryDisplay) {
        getBE().mHwc->onHotplug(display, connection);
        if (!mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY].get()) {
            createBuiltinDisplayLocked(DisplayDevice::DISPLAY_PRIMARY);
        }
        createDefaultDisplayDevice();
    } else {
        if (sequenceId != getBE().mComposerSequenceId) {
            return;
        }
        if (getBE().mHwc->isUsingVrComposer()) {
            ALOGE("External displays are not supported by the vr hardware composer.");
            return;
        }
        getBE().mHwc->onHotplug(display, connection);
        auto type = DisplayDevice::DISPLAY_EXTERNAL;
        if (connection == HWC2::Connection::Connected) {
            createBuiltinDisplayLocked(type);
        } else {
            mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
            mBuiltinDisplays[type].clear();
        }
        setTransactionFlags(eDisplayTransactionNeeded);
    }
}

接收到屏幕插拔事件后,主要做了如下的處理:

  • 通知HWC onHotplug

通過(guò)onHotplug通知HWC;如果是連接,HWC將去獲取新添加Display的config信息,如果是斷開(kāi),將HWC中的Display同步斷開(kāi)。

  • 創(chuàng)建Display的Token
    createBuiltinDisplayLocked如果是連接狀態(tài),都將通過(guò)createBuiltinDisplayLocked創(chuàng)建Display的Token。添加到mBuiltinDisplays中,mBuiltinDisplays它只是Display的IBinder列表,我們也稱之為T(mén)oken列表。
sp<IBinder> mBuiltinDisplays[DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES];

這個(gè)時(shí)候還沒(méi)有創(chuàng)建DisplayDevice,只是創(chuàng)建了一個(gè)Token而已。Display的Token通知添加到mCurrentState的displays中。

  • 創(chuàng)建主屏幕對(duì)應(yīng)的DisplayDevice

如果是主屏,還會(huì)通過(guò)createDefaultDisplayDevice創(chuàng)建默認(rèn)的DisplayDevice。

void SurfaceFlinger::createDefaultDisplayDevice() {
    const DisplayDevice::DisplayType type = DisplayDevice::DISPLAY_PRIMARY;
    wp<IBinder> token = mBuiltinDisplays[type];

    // All non-virtual displays are currently considered secure.
    const bool isSecure = true;

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

    sp<FramebufferSurface> fbs = new FramebufferSurface(*getBE().mHwc, type, consumer);

    bool hasWideColorModes = false;
    std::vector<android_color_mode_t> modes = getHwComposer().getColorModes(type);
    for (android_color_mode_t colorMode : modes) {
        switch (colorMode) {
            case HAL_COLOR_MODE_DISPLAY_P3:
            case HAL_COLOR_MODE_ADOBE_RGB:
            case HAL_COLOR_MODE_DCI_P3:
                hasWideColorModes = true;
                break;
            default:
                break;
        }
    }
    bool useWideColorMode = hasWideColorModes && hasWideColorDisplay && !mForceNativeColorMode;
    sp<DisplayDevice> hw = new DisplayDevice(this, DisplayDevice::DISPLAY_PRIMARY, type, isSecure,
                                             token, fbs, producer, useWideColorMode);
    mDisplays.add(token, hw);
    android_color_mode defaultColorMode = HAL_COLOR_MODE_NATIVE;
    if (useWideColorMode) {
        defaultColorMode = HAL_COLOR_MODE_SRGB;
    }
    setActiveColorModeInternal(hw, defaultColorMode);
    hw->setCompositionDataSpace(HAL_DATASPACE_UNKNOWN);

    // Add the primary display token to mDrawingState so we don't try to
    // recreate the DisplayDevice for the primary display.
    mDrawingState.displays.add(token, DisplayDeviceState(type, true));

    // make the GLContext current so that we can create textures when creating
    // Layers (which may happens before we render something)
    hw->makeCurrent();
}
  • 看到?jīng)]有,主Display的BufferQueue是就是此時(shí)創(chuàng)建的。并且創(chuàng)建了前面所說(shuō)的FramebufferSurface,這就是FBTarget。
  • DisplayDevice對(duì)應(yīng)的類型為DISPLAY_PRIMARY,創(chuàng)建了DisplayDevice后,添加到mDisplays中。而Display的Token被添加到mDrawingState的displays中,注意,是mDrawingState。
  • 這里還有顏色模式Colormode和數(shù)據(jù)空間DataSpace的設(shè)置,這兩個(gè)概念后續(xù)介紹。
  • 最后,調(diào)用makeCurrent,表示該DisplayDevice進(jìn)入可用狀態(tài)
bool DisplayDevice::makeCurrent() const {
    bool success = mFlinger->getRenderEngine().setCurrentSurface(mSurface);
    setViewportAndProjection();
    return success;
}

makeCurrent主要做了兩件事:其一,設(shè)置RenderEngine的Surface,這個(gè)Surface封裝了前面BufferQueue中創(chuàng)建的Producer,以及對(duì)應(yīng)的NativeWindow;其二,設(shè)置Display的Viewport和Projection,做過(guò)OpengGL開(kāi)發(fā)的,對(duì)這個(gè)應(yīng)該沒(méi)有什么難題,視窗大小和投影矩陣。也是設(shè)置到RenderEngine中,GPU合成用。

  • 非主屏刪除處理
    非主屏?xí)r刪除時(shí),將Display的Token從mBuiltinDisplays中刪掉,且Token也從mCurrentState中刪掉。注意,這里的是mCurrentState。主屏一般只會(huì)添加一次,沒(méi)有斷開(kāi)操縱,斷開(kāi)時(shí)系統(tǒng)已經(jīng)關(guān)了。

  • Transaction處理
    連接或斷開(kāi)顯示屏,也算是一種Transaction。通過(guò)setTransactionFlags,設(shè)置處理的flag eDisplayTransactionNeeded。

到此,連接時(shí),主顯的Token是添加到mDrawingState中的,已經(jīng)創(chuàng)建對(duì)應(yīng)的DisplayDevice,且沒(méi)有斷開(kāi)處理。而非主顯只創(chuàng)建了Display的Token,添加到這里的是mCurrentState中,還沒(méi)有創(chuàng)建對(duì)應(yīng)的DisplayDevice,斷開(kāi)的屏幕,Token從mCurrentState刪除。簡(jiǎn)單點(diǎn)來(lái)說(shuō),mDrawingState中的Token都創(chuàng)建了DisplayDevice;在mCurrentState中的不再mDrawingState中的,都是添加的;在mDrawingState中的,不在mCurrentState中的都是斷開(kāi)的。

創(chuàng)建DisplayDevice

上面設(shè)置的setTransactionFlags什么時(shí)候處理?Vsync來(lái)的時(shí)候,Vsync來(lái)后,通過(guò)INVALIDATE消息,又回到SurfaceFlinger處理。中間的過(guò)程稍后介紹,我們直接看對(duì)這里設(shè)置的eDisplayTransactionNeeded的處理流程。

處理eDisplayTransactionNeeded時(shí),其實(shí)就是同步 mDrawingState 和 mCurrentState 中displays。

  • 屏幕斷開(kāi)時(shí)的處理
    先處理刪除的Display,屏幕的Token在mDrawingState中的,不在mCurrentState中的都是斷開(kāi)的。邏輯如下:
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
            ``` ```
    if (transactionFlags & eDisplayTransactionNeeded) {
        const KeyedVector<  wp<IBinder>, DisplayDeviceState>& curr(mCurrentState.displays);
        const KeyedVector<  wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
        if (!curr.isIdenticalTo(draw)) {
            mVisibleRegionsDirty = true;
            const size_t cc = curr.size();
                  size_t dc = draw.size();

            for (size_t i=0 ; i<dc ;) {
                const ssize_t j = curr.indexOfKey(draw.keyAt(i));
                if (j < 0) {
                    if (!draw[i].isMainDisplay()) {
                        const sp<const DisplayDevice> defaultDisplay(getDefaultDisplayDeviceLocked());
                        defaultDisplay->makeCurrent();
                        sp<DisplayDevice> hw(getDisplayDeviceLocked(draw.keyAt(i)));
                        if (hw != NULL)
                            hw->disconnect(getHwComposer());
                        if (draw[i].type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES)
                            mEventThread->onHotplugReceived(draw[i].type, false);
                        mDisplays.removeItem(draw.keyAt(i));
                    } else {
                        ALOGW("trying to remove the main display");
                    }
                } else {
                    // this display is in both lists. see if something changed.
                    const DisplayDeviceState& state(curr[j]);
                    const wp<IBinder>& display(curr.keyAt(j));
                    const sp<IBinder> state_binder = IInterface::asBinder(state.surface);
                    const sp<IBinder> draw_binder = IInterface::asBinder(draw[i].surface);
                    if (state_binder != draw_binder) {
                        sp<DisplayDevice> hw(getDisplayDeviceLocked(display));
                        if (hw != NULL)
                            hw->disconnect(getHwComposer());
                        mDisplays.removeItem(display);
                        mDrawingState.displays.removeItemsAt(i);
                        dc--;
                        // at this point we must loop to the next item
                        continue;
                    }

                    const sp<DisplayDevice> disp(getDisplayDeviceLocked(display));
                    if (disp != NULL) {
                        if (state.layerStack != draw[i].layerStack) {
                            disp->setLayerStack(state.layerStack);
                        }
                        if ((state.orientation != draw[i].orientation)
                                || (state.viewport != draw[i].viewport)
                                || (state.frame != draw[i].frame))
                        {
                            disp->setProjection(state.orientation,
                                    state.viewport, state.frame);
                        }
                        if (state.width != draw[i].width || state.height != draw[i].height) {
                            disp->setDisplaySize(state.width, state.height);
                        }
                    }
                }
                ++i;
            }

如果Token在mDrawingState中,而沒(méi)有在mCurrentState中,說(shuō)明這個(gè)屏已經(jīng)被斷開(kāi)了,需要?jiǎng)h掉DisplayDevice。如果Token在兩個(gè)狀態(tài)中都存在,有修改,暫時(shí)將Token中mDrawingState刪掉。注意兩個(gè)狀態(tài)啊,要不然理解不對(duì)。

斷開(kāi)時(shí),調(diào)用DisplayDevice的disconnect,這其中將調(diào)用HWC中,HWC中創(chuàng)建的對(duì)應(yīng)的Device也將被刪除。同時(shí)將DisplayDevice從mDisplays中刪除。

  • 處理添加的Display
    屏幕的Token在mCurrentState中的不再mDrawingState中的,都是添加的;處理邏輯如下。
void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
{
            ``` ```
            for (size_t i=0 ; i<cc ; i++) {
                if (draw.indexOfKey(curr.keyAt(i)) < 0) {
                    const DisplayDeviceState& state(curr[i]);

                    sp<DisplaySurface> dispSurface;
                    sp<IGraphicBufferProducer> producer;
                    sp<IGraphicBufferProducer> bqProducer;
                    sp<IGraphicBufferConsumer> bqConsumer;
                    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer);

                    int32_t hwcId = -1;
                    if (state.isVirtualDisplay()) {
                        // Virtual displays without a surface are dormant:
                        // they have external state (layer stack, projection,
                        // etc.) but no internal state (i.e. a DisplayDevice).
                        if (state.surface != NULL) {

                            // 虛擬顯示用硬件
                            ... ...

                            sp<VirtualDisplaySurface> vds =
                                    new VirtualDisplaySurface(*getBE().mHwc,
                                            hwcId, state.surface, bqProducer,
                                            bqConsumer, state.displayName);

                            dispSurface = vds;
                            producer = vds;
                        }
                    } else {
                        ALOGE_IF(state.surface!=NULL,
                                "adding a supported display, but rendering "
                                "surface is provided (%p), ignoring it",
                                state.surface.get());

                        hwcId = state.type;
                        dispSurface = new FramebufferSurface(*getBE().mHwc, hwcId, bqConsumer);
                        producer = bqProducer;
                    }

                    const wp<IBinder>& display(curr.keyAt(i));
                    if (dispSurface != NULL) {
                        sp<DisplayDevice> hw =
                                new DisplayDevice(this, state.type, hwcId, state.isSecure, display,
                                                  dispSurface, producer, hasWideColorDisplay);
                        hw->setLayerStack(state.layerStack);
                        hw->setProjection(state.orientation,
                                state.viewport, state.frame);
                        hw->setDisplayName(state.displayName);
                        mDisplays.add(display, hw);
                        if (!state.isVirtualDisplay()) {
                            mEventThread->onHotplugReceived(state.type, true);
                        }
                    }
                }
            }
        }
    }
            ... ...

添加屏幕時(shí),根據(jù)前面已經(jīng)創(chuàng)建的BufferQueue,創(chuàng)建對(duì)應(yīng)的DisplaySurface,外顯和虛顯的不一樣。創(chuàng)建DisplaySurface后,再創(chuàng)建DisplayDevice;設(shè)置DisplayDevice的stack,投影矩陣Projection;將創(chuàng)建的DisplayDevice添加到mDisplays中;最后,對(duì)外顯,調(diào)用EventThread的onHotplugReceived。

EventThread的onHotplugReceived函數(shù)中,將封裝一個(gè)hotplug的Event事件DISPLAY_EVENT_HOTPLUG,EventThread再將事件分發(fā)出去。這里對(duì)hotplug感興趣的主要就是框架層了,回調(diào)給DisplayManagerService。

hotplug的流程

這里主要將了Display相關(guān)的邏輯,主要是熱插拔的處理。下面是整個(gè)Android系統(tǒng)添加屏幕時(shí)的處理流程。


Display熱插拔的流程

Display相關(guān)的就介紹到這里,后續(xù)講合成時(shí),還會(huì)有很多相關(guān)的流程。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容