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

时间:2024-04-13 11:58:00

编写app

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

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

 

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

booleanonKeyDown(int keyCode,KeyEvent event) 按键

boolean onTouchEvent(MotionEvent event)   触摸屏

 

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

 

第二课

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

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

下图为分析的框架


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

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

 

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);读取产生的输入事件,//mEventHubEventHub.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); //进入notifymInnerListener其实就是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)

mDispatcherinputmanager.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驱动编写流程:

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

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

Linux系统所支持的事件

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

4课内核输入子系统原理分析

1子系统核心架构

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

2注册输入设备

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

2.1那设备idhandleid进行匹配,找到合适的处理者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_devhandler

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

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

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

//如果是按键事件,就会调用evdev.cstruct 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上报事件(以按键事件为例

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

-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.cinput_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.cinput_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