天天看點

surfaceflinger增加hdmi顯示裝置

1:當hdmi插入的時候,hdmi驅動會上報一個中斷上來,在驅動中會發送一個Uevent給上層。

“/sys/class/switch/hdmi/state” 這個節點會由0變成1

2:在HWC中,啟動的時候就開啟一個hdmi狀态監聽的線程,當這個節點有變化的時候,會去設定hdmi分辨率,打開hdmi裝置,而且還更新自己的節點狀态。

根據上面的hdmi使能之後,調用到:

HWC_OWL_ContextHotplugDisplay()來更新hdmi的狀态,主要是向上層報告增加了一個hdmi裝置。

代碼如下:

//這裡會回調到HWComposer中的接口

pthread_mutex_lock(&psPrivateData->sHdmiMutexLock);
        psHwcFuncs->pfnContextHotplugDisplay(psPrivateData,eDisplay, bConnected);   
        pthread_mutex_unlock(&psPrivateData->sHdmiMutexLock);
        psPrivateData->psHwcProcs->hotplug(psPrivateData->psHwcProcs, iDisplay,  iConnected);       
           

3:回到HWComposer中,來看下hotplug接口:

void HWComposer::hotplug(int disp, int connected) {
    if (disp == HWC_DISPLAY_PRIMARY || disp >= VIRTUAL_DISPLAY_ID_BASE) {
        ALOGE("hotplug event received for invalid display: disp=%d connected=%d",
                disp, connected);
        return;
    }
    queryDisplayProperties(disp); //得到顯示裝置的配置資訊,比如分辨率 density等資訊
    mEventHandler.onHotplugReceived(disp, bool(connected)); //注意這個mEventHandler其實就是surfaceflinger對象,在HWC的構造函數中指派
           

}

4:看下SF中的onHotplugReceived()

void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
    if (uint32_t(type) < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
        Mutex::Autolock _l(mStateLock);
        if (connected) {
//将HDMI裝置加入到全局的display清單中
            createBuiltinDisplayLocked((DisplayDevice::DisplayType)type);
        } else {
            mCurrentState.displays.removeItem(mBuiltinDisplays[type]);
            mBuiltinDisplays[type].clear();
        }
        setTransactionFlags(eDisplayTransactionNeeded);//設定transactionFlags為eDisplayTransactionNeeded 這個變量會在下一個vsync信号來臨的時候去建立新的顯示裝置
    }
           

5:業務處理

SurfaceFlinger::handleTransactionLocked()中,
     for (size_t i= ; i<cc ; i++) {               
                //1:建立createBufferQueue
                    BufferQueue::createBufferQueue(&bqProducer, &bqConsumer,
                            new GraphicBufferAlloc());
                        hwcDisplayId = allocateHwcDisplayId(state.type);
                        dispSurface = new FramebufferSurface(*mHwc, state.type,
                                bqConsumer);
                        producer = bqProducer;
                    }
                    const wp<IBinder>& display(curr.keyAt(i));
                    if (dispSurface != NULL) {
                    //2:建立DisplayDevice
                        sp<DisplayDevice> hw = new DisplayDevice(this,
                                state.type, hwcDisplayId,
                                mHwc->getFormat(hwcDisplayId), state.isSecure,
                                display, dispSurface, producer,
                                mRenderEngine->getEGLConfig());
                        hw->setLayerStack(state.layerStack);
                        hw->setProjection(state.orientation,
                                state.viewport, state.frame);
                        hw->setDisplayName(state.displayName);
                        mDisplays.add(display, hw);
                        //喚醒vsync線程
                            mEventThread->onHotplugReceived(state.type, true);
                        }
                    }
                }
            }
        }
    }
           

6:在EventThread中看下這個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;
        //這裡設定的type為DISPLAY_EVENT_HOTPLUG
        event.header.type = DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG;
        event.header.id = type;
        event.header.timestamp = systemTime();
        event.hotplug.connected = connected;
        mPendingEvents.add(event);
        //喚醒vsync線程
        mCondition.broadcast();
    }
}
           

6:在EventThread::threadLoop()中将上面的消息通過BitTube發送出去

//在onHotplugReceived中已經把它喚醒
    signalConnections = waitForEvent(&event);

    // dispatch events to listeners...
    const size_t count = signalConnections.size();
    for (size_t i= ; i<count ; i++) {
        const sp<Connection>& conn(signalConnections[i]);
        // now see if we still need to report this event
        //将event事件發送出去
        status_t err = conn->postEvent(event);
  //具體postEvent的實作    
status_t EventThread::Connection::postEvent(
        const DisplayEventReceiver::Event& event) {
    ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, );
    return size <  ? status_t(size) : status_t(NO_ERROR);
}
//sendEvents的實作
ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,
        Event const* events, size_t count)
{
    return BitTube::sendObjects(dataChannel, events, count);
}
           

上層接收Vsync和DISPLAY_EVENT_HOTPLUG事件的接收者是:NativeDisplayEventReceiver

會直接調用它的方法:NativeDisplayEventReceiver::handleEvent方法;

具體接收流程在另外一篇文章中做了詳細說明:http://blog.csdn.net/u010865783/article/details/54616739

這篇文章是對那篇文章底層hdmi插拔事件的一個補充。

繼續閱讀