本文实例讲述了AndroID编程输入事件流程。分享给大家供大家参考,具体如下:
EventHub对输入设备进行了封装。输入设备驱动程序对用户空间应用程序提供一些设备文件,这些设备文件放在/dev/input里面。
EventHub扫描/dev/input下所有设备文件,并打开它们。
bool EventHub::openPlatforminput(voID){... mFDCount = 1; mFDs = (pollfd *)calloc(1,sizeof(mFDs[0])); mDevices = (device_t **)calloc(1,sizeof(mDevices[0])); mFDs[0].events = PolliN; mDevices[0] = NulL; res = scan_dir(device_path);... return true;}
EventHub对外提供了一个函数用于从输入设备文件中读取数据。
bool EventHub::getEvent(int32_t* outdeviceid,int32_t* outType,int32_t* outScancode,int32_t* outKeycode,uint32_t *outFlags,int32_t* outValue,nsecs_t* outWhen) { ... while(1) { // First,report any devices that had last been added/removed. if (mClosingDevices != NulL) { device_t* device = mClosingDevices; LOGV("Reporting device closed: ID=0x%x,name=%s\n",device->ID,device->path.string()); mClosingDevices = device->next; *outdeviceid = device->ID; if (*outdeviceid == mFirstKeyboardID) *outdeviceid = 0; *outType = DEVICE_REMOVED; delete device; return true; } if (mopeningDevices != NulL) { device_t* device = mopeningDevices; LOGV("Reporting device opened: ID=0x%x,device->path.string()); mopeningDevices = device->next; *outdeviceid = device->ID; if (*outdeviceid == mFirstKeyboardID) *outdeviceid = 0; *outType = DEVICE_ADDED; return true; } release_wake_lock(WAKE_LOCK_ID); pollres = poll(mFDs,mFDCount,-1); acquire_wake_lock(PARTIAL_WAKE_LOCK,WAKE_LOCK_ID); if (pollres <= 0) { if (errno != EINTR) { LOGW("select Failed (errno=%d)\n",errno); usleep(100000); } continue; } for(i = 1; i < mFDCount; i++) { if(mFDs[i].revents) { LOGV("revents for %d = 0x%08x",i,mFDs[i].revents); if(mFDs[i].revents & PolliN) { res = read(mFDs[i].fd,&IEv,sizeof(IEv)); if (res == sizeof(IEv)) { LOGV("%s got: t0=%d,t1=%d,type=%d,code=%d,v=%d",mDevices[i]->path.string(),(int) IEv.time.tv_sec,(int) IEv.time.tv_usec,IEv.type,IEv.code,IEv.value); *outdeviceid = mDevices[i]->ID; if (*outdeviceid == mFirstKeyboardID) *outdeviceid = 0; *outType = IEv.type; *outScancode = IEv.code; if (IEv.type == EV_KEY) { err = mDevices[i]->layoutMap->map(IEv.code,outKeycode,outFlags); LOGV("IEv.code=%d outKeycode=%d outFlags=0x%08x err=%d\n",*outKeycode,*outFlags,err); if (err != 0) { *outKeycode = 0; *outFlags = 0; } } else { *outKeycode = IEv.code; } *outValue = IEv.value; *outWhen = s2ns(IEv.time.tv_sec) + us2ns(IEv.time.tv_usec); return true; } else { if (res<0) { LOGW("Could not get event (errno=%d)",errno); } else { LOGE("Could not get event (wrong size: %d)",res); } continue; } } } } ...}
对于按键事件,调用mDevices[i]->layoutMap->map进行映射。映射实际是由 KeyLayoutMap::map完成的,KeyLayoutMap类里读取配置文件qwerty.kl,由配置文件qwerty.kl决定键值的映射关系。你可以通过修改./development/emulator/keymaps/qwerty.kl来改变键值的映射关系。
JNI函数
在frameworks/base/services/jni/com_androID_server_KeyinputQueue.cpp文件中,向JAVA提供了函数androID_server_KeyinputQueue_readEvent,用于读取输入设备事件。
static jbooleanandroID_server_KeyinputQueue_readEvent(jnienv* env,jobject clazz,jobject event){ gLock.lock(); sp hub = gHub; if (hub == NulL) { hub = new EventHub; gHub = hub; } gLock.unlock(); int32_t deviceid; int32_t type; int32_t scancode,keycode; uint32_t flags; int32_t value; nsecs_t when; bool res = hub->getEvent(&deviceid,&type,&scancode,&keycode,&flags,&value,&when); env->SetIntFIEld(event,ginputOffsets.mdeviceid,(jint)deviceid); env->SetIntFIEld(event,ginputOffsets.mType,(jint)type); env->SetIntFIEld(event,ginputOffsets.mScancode,(jint)scancode); env->SetIntFIEld(event,ginputOffsets.mKeycode,(jint)keycode); env->SetIntFIEld(event,ginputOffsets.mFlags,(jint)flags); env->SetIntFIEld(event,ginputOffsets.mValue,value); env->SetLongFIEld(event,ginputOffsets.mWhen,(jlong)(nanoseconds_to_milliseconds(when))); return res;}
readEvent调用hub->getEvent读了取事件,然后转换成JAVA的结构。
事件中转线程
在frameworks/base/services/java/com/androID/server/KeyinputQueue.java里创建了一个线程,它循环的读取事件,然后把事件放入事件队列里。
Thread mThread = new Thread("inputDeviceReader") { public voID run() { androID.os.Process.setThreadPriority( androID.os.Process.THREAD_PRIORITY_URGENT_disPLAY); try { RawinputEvent ev = new RawinputEvent(); while (true) { inputDevice di; readEvent(ev); send = preprocessEvent(di,ev); addLocked(di,curTime,ev.flags,...,me); } } };}
输入事件分发线程
在frameworks/base/services/java/com/androID/server/WindowManagerService.java里创建了一个输入事件分发线程,它负责把事件分发到相应的窗口上去。
mQueue.getEventdispatchKey/dispatchPointer/dispatchtrackball
更多关于AndroID相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android多媒体 *** 作技巧汇总(音频,视频,录音等)》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》
希望本文所述对大家AndroID程序设计有所帮助。
总结以上是内存溢出为你收集整理的Android编程输入事件流程详解全部内容,希望文章能够帮你解决Android编程输入事件流程详解所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)