您的位置:首页 > 移动开发 > Android开发

android系统中input驱动整体框架分析

2016-12-24 21:21 375 查看
编写app,

1:完成对触摸屏和按键事件的捕捉

2:检测输入设备的插入和拔出(热插拔)

 

需要用到的activity类中的方法:

booleanonKeyDown(int keyCode,KeyEvent
event) 按键

boolean
onTouchEvent(MotionEvent
event)   触摸屏

 

 

 

第二课
框架层分析:

下图为分析的框架



 


 

1.整体架构的分析(InputDispatcher是监听器,一旦InputReader接收到事件,便会通知InputDispatcher对事件进行处理)
进入inputmanager.cpp

-》status_t InputManager::start()此处产生俩个线程分支

分支1:主要负责分发事件(InputDispatcher:监听器)

-》mDispatcherThread->run("InputDispatcher",PRIORITY_URGENT_DISPLAY);

进入threads.cpp文件

-》status_t Thread::run(const char*name, int32_t
priority, size_t stack)

-》res = androidCreateRawThreadEtc(_threadLoop,this,
name, priority, stack, &mThread);

//调用线程对象中的_threadLoop函数

进入inputDispatcher.cpp

-》boolInputDispatcherThread::threadLoop()

-》void InputDispatcher::dispatchOnce()

分支2:主要负责读取事件(InputReader)

-》mReaderThread->run("InputReader",PRIORITY_URGENT_DISPLAY);

进入threads.cpp文件

-》status_t Thread::run(const char*name, int32_t
priority, size_t stack)

-》res = androidCreateRawThreadEtc(_threadLoop,this,
name, priority, stack, &mThread);

//调用线程对象中的_threadLoop函数

进入inputReader.cpp

-》bool InputReaderThread::threadLoop()

-》mReader->loopOnce(); 

-》size_tcount=mEventHub->getEvents(timeoutMillis,mEventBuffer,EVENT_BUFFER_SIZE);读取产生的输入事件
2.读取事件的流程:

进入inputmanager.cpp

-》status_t InputManager::start()此处产生俩个线程分支

-》mReaderThread->run("InputReader",PRIORITY_URGENT_DISPLAY);

进入threads.cpp文件

-》status_t Thread::run(const char*name, int32_t
priority, size_t stack)

-》res = androidCreateRawThreadEtc(_threadLoop,this,
name, priority, stack, &mThread);

//调用线程对象中的_threadLoop函数

进入inputReader.cpp

-》bool InputReaderThread::threadLoop()

-》mReader->loopOnce(); 

分支1:

-》mEventHub->getEvents(timeoutMillis,mEventBuffer,
EVENT_BUFFER_SIZE);读取产生的输入事件,//mEventHub在EventHub.cpp中

进入EventHub.cpp

-》size_t EventHub::getEvents(int timeoutMillis,RawEvent*
buffer, size_t bufferSize)

-》通过系统调用read函数读取事件

分支2:返回inputReader.cpp

-》mQueuedListener->flush(); //把读取的事件告诉inputdispatcher

进入inputlistener.cpp

-》void QueuedInputListener::flush()

-》args->notify(mInnerListener); //进入notify,mInnerListener其实就是mDispatcher

分支2.1按键事件

-》voidNotifyKeyArgs::notify(const sp<InputListenerInterface>&listener)
const {

listener->notifyKey(this);(按键事件调用此notify)

-》voidInputDispatcher::notifyKey(const NotifyKeyArgs* args)调用inputdispatcher.cpp中的notifyKey(this)函数

分支2.2设备置位事件

-》voidNotifyDeviceResetArgs::notify(const sp<InputListenerInterface>&listener)

-》listener->notifyDeviceReset(this); //调用的是inputdispatcher.cpp中的notifyDeviceReset(this)函数

进入inputdispatcher.cpp

-》void InputDispatcher::notifyDeviceReset(constNotifyDeviceResetArgs*
args)

mDispatcher(inputmanager.cpp)-》listener(inputreader.cpp)-》InnerListener(inputlistener.cpp)-》mInnerListener(inputlistener.cpp)-》Listener(inputlistener.cpp)

 

3.分发事件3.1对事件分类;3.2找到分发的目标3.3分发(socket机制)

-》进入inputmanager.cpp

-》status_t InputManager::start()此处产生俩个线程分支

分支1:主要负责分发事件(InputDispatcher:监听器)

-》mDispatcherThread->run("InputDispatcher",
PRIORITY_URGENT_DISPLAY);

进入threads.cpp文件

-》status_t Thread::run(const char*name, int32_t
priority, size_t stack)

-》res = androidCreateRawThreadEtc(_threadLoop,this,
name, priority, stack, &mThread);

//调用线程对象中的_threadLoop函数

进入inputDispatcher.cpp

-》bool InputDispatcherThread::threadLoop()

-》void InputDispatcher::dispatchOnce()

-》dispatchOnceInnerLocked(&nextWakeupTime);  //进入此函数

-》switch (mPendingEvent->type) {}//对inputreader传给的时间进行分类

-》如果是按键事件,就会调用:dispatchKeyLocked(currentTime,typedEntry,
&dropReason, nextWakeupTime); //对事件进行处理

-》int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,entry,inputTargets,
nextWakeupTime);确定分发目标,即发给那个窗口

-》dispatchEventLocked(currentTime,entry, inputTargets);//分发按键事件

-》ssize_t connectionIndex =getConnectionIndexLocked(inputTarget.inputChannel);建立连接

-》prepareDispatchCycleLocked(currentTime,connection,
eventEntry, &inputTarget); //进行通信,进入分析

-》enqueueDispatchEntriesLocked(currentTime,connection,
splitMotionEntry, inputTarget);

-》startDispatchCycleLocked(currentTime,connection);  //进入分析

-》switch (eventEntry->type){}

-》(分发按键事件)Publish the key event.

status =connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,

                  keyEntry->deviceId,keyEntry->source,

                 
dispatchEntry->resolvedAction,dispatchEntry->resolvedFlags,

                 
keyEntry->keyCode,keyEntry->scanCode,

                 
keyEntry->metaState,keyEntry->repeatCount,keyEntry->downTime,

                 
keyEntry->eventTime);

第三课(内核驱动分析)
1.    input驱动编写流程:



Linux系统所支持的事件

第4课内核输入子系统原理分析
1子系统核心架构



2注册输入设备:

2.1那设备id和handle的id进行匹配,找到合适的处理者handler

2.2调用handler中的connect函数创建设备文件

进入input.c

-》int input_register_device(structinput_dev *dev)

-》list_for_each_entry(handler,&input_handler_list,
node)input_attach_handler(dev, handler);  
//进入input_attach_handler函数//遍历input_handler_list链表中的所以handler,然后找出可以处理input_register_device(struct
input_dev *dev)函数中

//传入的input_dev的handler

-》static intinput_attach_handler(struct input_dev
*dev, struct input_handler *handler)

-》id = input_match_device(handler,dev); //通过设备和处理函数进行匹配,主要是通过事件驱动层的id和dev的id进行匹配

-》error = handler->connect(handler,dev, id); //如果匹配成功,开始建立连接

//如果是按键事件,就会调用evdev.c中struct
input_handler evdev_handler 结构中的connect函数

-》static int evdev_connect(structinput_handler
*handler, struct input_dev *dev,const struct input_device_id *id) 此函数会创建设备节点,并与在input.c中的input_init函数中注册的字符设备关联

 

3上报事件(以按键事件为例)

-》input_report_event() //在input.h中

-》input_event(dev, EV_KEY, code,!!value);

-》if (is_event_supported(type,dev->evbit, EV_MAX))//判断上报的事件之前是否用set_bit函数申明过

-》input_handle_event(dev, type, code,value);  //进入分析

-》input_pass_event(dev, type, code,value); //进入分析

-》handle->handler->event(handle,type, code, value);
//调用之前匹配好的handler中的event函数进行处,//如按键事件就会调用evdev.c中input_handler
evdev_handler = {.event             
= evdev_event函数

-》static void evdev_event(structinput_handle
*handle,unsigned int type, unsigned int code, int value)

-》对事件进行打包event.time.tv_sec = ts.tv_sec;

       event.time.tv_usec = ts.tv_nsec /NSEC_PER_USEC;

       event.type = type;

       event.code = code;

       event.value = value;

-》evdev_pass_event(client,&event); //进去此函数//把打包好的event事件保存在buffer中,当应用程序要读取事件是,就会从buffer中读取

 

4:应用程序读取事件过程;以read为例

进入input.c

-》static int __init input_init(void)

-》err = register_chrdev(INPUT_MAJOR,"input",
&input_fops);  //注册字符设备驱动

-》static const struct file_operationsinput_fops
= {

       .owner = THIS_MODULE,

       .open = input_open_file, //进入打开函数

       .llseek = noop_llseek,

};

-》static int input_open_file(structinode *inode,
struct file *file)

-》new_fops = fops_get(handler->fops);//把handler中的操作函数集赋值给new_fops

-》 file->f_op=
new_fops; //换成新的操作函数集

-》之后会进入event.c中,调用static
struct input_handler evdev_handler = {

       .event          =evdev_event, //事件处理函数

       .connect=evdev_connect, //连接函数,主要用于创建设备节点,并与input.c中input_init函数中注册的驱动关联

       .disconnect  = evdev_disconnect,

       .fops            =&evdev_fops,

       .minor          =EVDEV_MINOR_BASE,

       .name          ="evdev",

       .id_table=evdev_ids,

};中的fops

-》static const struct file_operationsevdev_fops
= {

       .owner         =THIS_MODULE,

       .read            =evdev_read,

       .write           =evdev_write,

       .poll      =evdev_poll,

       .open           =evdev_open,

       .release =evdev_release,

       .unlocked_ioctl   = evdev_ioctl,

#ifdefCONFIG_COMPAT

       .compat_ioctl     = evdev_ioctl_compat,

#endif

       .fasync        =evdev_fasync,

       .flush           =evdev_flush,

       .llseek          =no_llseek,

};

-》static ssize_t evdev_read(struct file*file,
char __user *buffer,size_t count, loff_t *ppos)

-》evdev_fetch_next_event(client,&event)) { //从buffer中读取保存的事件,

-》input_event_to_user(buffer + retval,&event)
//把事件提交给用户空间

-》copy_to_user(buffer, event,sizeof(struct input_event))//在input-compat.c中
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐