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插拔事件的一個補充。