Android应用程序键盘(Keyboard)消息处理机制分析(4)
Step 18. EventHub.getEvent 这个函数定义在frameworks/base/libs/ui/EventHub.cpp文件中: boolEventHub::getEvent(RawEvent*outEvent) { outEvent->deviceId=0; outEvent->type=0; outEvent->scanCode=0; outEvent->keyCode=0; outEvent->flags=0; outEvent->value=0; outEvent->when=0; //NotethatweonlyallowonecallertogetEvent(),sodon'tneed //todolockinghere...onlywhenadding/removingdevices. if(!mOpened){ mError=openPlatformInput()?NO_ERROR:UNKNOWN_ERROR; mOpened=true; mNeedToSendFinishedDeviceScan=true; } for(;;){ //Reportanydevicesthathadlastbeenadded/removed. if(mClosingDevices!=NULL){ device_t*device=mClosingDevices; LOGV("Reportingdeviceclosed:id=0x%x,name=%s\n", device->id,device->path.string()); mClosingDevices=device->next; if(device->id==mFirstKeyboardId){ outEvent->deviceId=0; }else{ outEvent->deviceId=device->id; } outEvent->type=DEVICE_REMOVED; outEvent->when=systemTime(SYSTEM_TIME_MONOTONIC); deletedevice; mNeedToSendFinishedDeviceScan=true; returntrue; } if(mOpeningDevices!=NULL){ device_t*device=mOpeningDevices; LOGV("Reportingdeviceopened:id=0x%x,name=%s\n", device->id,device->path.string()); mOpeningDevices=device->next; if(device->id==mFirstKeyboardId){ outEvent->deviceId=0; }else{ outEvent->deviceId=device->id; } outEvent->type=DEVICE_ADDED; outEvent->when=systemTime(SYSTEM_TIME_MONOTONIC); mNeedToSendFinishedDeviceScan=true; returntrue; } if(mNeedToSendFinishedDeviceScan){ mNeedToSendFinishedDeviceScan=false; outEvent->type=FINISHED_DEVICE_SCAN; outEvent->when=systemTime(SYSTEM_TIME_MONOTONIC); returntrue; } //Grabthenextinputevent. for(;;){ //Consumebufferedinputevents,ifany. if(mInputBufferIndex<mInputBufferCount){ conststructinput_event&iev=mInputBufferData[mInputBufferIndex++]; constdevice_t*device=mDevices[mInputDeviceIndex]; LOGV("%sgot:t0=%d,t1=%d,type=%d,code=%d,v=%d",device->path.string(), (int)iev.time.tv_sec,(int)iev.time.tv_usec,iev.type,iev.code,iev.value); if(device->id==mFirstKeyboardId){ outEvent->deviceId=0; }else{ outEvent->deviceId=device->id; } outEvent->type=iev.type; outEvent->scanCode=iev.code; if(iev.type==EV_KEY){ status_terr=device->layoutMap->map(iev.code, &outEvent->keyCode,&outEvent->flags); LOGV("iev.code=%dkeyCode=%dflags=0x%08xerr=%d\n", iev.code,outEvent->keyCode,outEvent->flags,err); if(err!=0){ outEvent->keyCode=AKEYCODE_UNKNOWN; outEvent->flags=0; } }else{ outEvent->keyCode=iev.code; } outEvent->value=iev.value; //Useaneventtimestampinthesametimebaseas //java.lang.System.nanoTime()andandroid.os.SystemClock.uptimeMillis() //asexpectedbytherestofthesystem. outEvent->when=systemTime(SYSTEM_TIME_MONOTONIC); returntrue; } //Finishreadingalleventsfromdevicesidentifiedinpreviouspoll(). //ThiscodeassumesthatmInputDeviceIndexisinitially0andthatthe //reventsmemberofpollfdisinitializedto0whenthedeviceisfirstadded. //SincemFDs[0]isusedforinotify,weprocessregulareventsstartingatindex1. mInputDeviceIndex+=1; if(mInputDeviceIndex>=mFDCount){ break; } conststructpollfd&pfd=mFDs[mInputDeviceIndex]; if(pfd.revents&POLLIN){ int32_treadSize=read(pfd.fd,mInputBufferData, sizeof(structinput_event)*INPUT_BUFFER_SIZE); if(readSize<0){ if(errno!=EAGAIN&&errno!=EINTR){ LOGW("couldnotgetevent(errno=%d)",errno); } }elseif((readSize%sizeof(structinput_event))!=0){ LOGE("couldnotgetevent(wrongsize:%d)",readSize); }else{ mInputBufferCount=readSize/sizeof(structinput_event); mInputBufferIndex=0; } } } ...... mInputDeviceIndex=0; //Pollforevents.Mindthewakelockdance! //Weholdawakelockatalltimesexceptduringpoll().Thisworksduetosome //subtlechoreography.Whenadevicedriverhaspending(unread)events,itacquires //akernelwakelock.However,oncethelastpendingeventhasbeenread,thedevice //driverwillreleasethekernelwakelock.Topreventthesystemfromgoingtosleep //whenthishappens,theEventHubholdsontoitsownuserwakelockwhiletheclient //isprocessingevents.Thusthesystemcanonlysleepiftherearenoevents //pendingorcurrentlybeingprocessed. release_wake_lock(WAKE_LOCK_ID); intpollResult=poll(mFDs,mFDCount,-1); acquire_wake_lock(PARTIAL_WAKE_LOCK,WAKE_LOCK_ID); if(pollResult<=0){ if(errno!=EINTR){ LOGW("pollfailed(errno=%d)\n",errno); usleep(100000); } } } } 这个函数比较长,我们一步一步来分析。 首先,如果是第一次进入到这个函数中时,成员变量mOpened的值为false,于是就会调用openPlatformInput函数来打开系统输入设备,在本文中,我们主要讨论的输入设备就是键盘了。打开了这些输入设备文件后,就可以对这些输入设备进行是监控了。如果不是第一次进入到这个函数,那么就会分析当前有没有输入事件发生,如果有,就返回这个事件,否则就会进入等待状态,等待下一次输入事件的发生。在我们这个场景中,就是等待下一次键盘事件的发生了。 我们先分析openPlatformInput函数的实现,然后回过头来分析这个getEvent函数的具体的实现。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966613,如需转载请自行联系原作者