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=0 ; 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=0 ; iconst sp& 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, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}
//sendEvents的实现
ssize_t DisplayEventReceiver::sendEvents(const sp& 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插拔事件的一个补充。