android input system(frameworks) analysis -- InputManager (1)

来源:互联网 发布:网络40大禁书海岸线 编辑:程序博客网 时间:2024/04/30 01:21

http://blog.csdn.net/darkengine/article/details/6956802

对input系统在framework层的分析从一次触摸屏丢失上报事件开始:由于设备节点/dev/input/input0存在,而且getevent能响应点触摸屏的动作,所以把问题定位到了EventHub和InputManager这一层。


InputManager的结构很简单,对外开放

[plain] view plaincopy
  1. virtual status_t start();  
  2. virtual status_t stop();  
  3. virtual sp<InputReaderInterface> getReader();  
  4. virtual sp<InputDispatcherInterface> getDispatcher();  

四个成员函数,内部带有私有成员

[plain] view plaincopy
  1. sp<InputReaderInterface> mReader;  
  2. sp<InputReaderThread> mReaderThread;  
  3. sp<InputDispatcherInterface> mDispatcher;  
  4. sp<InputDispatcherThread> mDispatcherThread;  
其构造过程也很简单:

[plain] view plaincopy
  1. mDispatcher = new InputDispatcher(dispatcherPolicy);  -- 根据输入的参数构造一个dispatcher  
  2. mReader = new InputReader(eventHub, readerPolicy, mDispatcher); -- 根据参数构造一个inputreader  
  3. initialize();  

[plain] view plaincopy
  1. void InputManager::initialize() {  
  2.     mReaderThread = new InputReaderThread(mReader); -- 产生reader线程用于从设备节点读取input event  
  3.     mDispatcherThread = new InputDispatcherThread(mDispatcher); -- 产生dispachter线程分发event  
  4. }  
InputManager的start主要就是让这两个线程跑起来:

[plain] view plaincopy
  1. status_t InputManager::start() {  
  2.     status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);  
  3.                ...  
  4.     result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);  
  5.                ...  
  6.     return OK;  
  7. }  

====================================================================================================================

接着先来分析InputReader:

InputReaderThread run之后会重复的调用

[plain] view plaincopy
  1. bool InputReaderThread::threadLoop() {  
  2.     mReader->loopOnce();  
  3.     return true;  
  4. }  

亦即mReader->loopOnce();

[plain] view plaincopy
  1. void InputReader::loopOnce() {  
  2.     RawEvent rawEvent;  
  3.     mEventHub->getEvent(& rawEvent);  
  4.     process(& rawEvent);  
  5. }  


InputReader上来就找EventHub要数据(getEvent()),所以我们要先看看EventHub的getEvent都做了些什么工作:

[cpp] view plaincopy
  1. bool EventHub::getEvent(RawEvent* outEvent)  
  2. {  
  3.     outEvent->deviceId = 0;  
  4.           ...  
  5.   
  6.     // 第一次调用getEvent的时候,需要调用openPlatformInput来搜索输入系统来查找可用的设备  
  7.     if (!mOpened) {  
  8.         mError = openPlatformInput() ? NO_ERROR : UNKNOWN_ERROR;  
  9.         mOpened = true;  
  10.         mNeedToSendFinishedDeviceScan = true;  
  11.     }  
  12. }  
[cpp] view plaincopy
  1. bool EventHub::openPlatformInput(void)  
  2. {  
  3.     // 为poll()调用作准备  
  4.     mFDCount = 1;  
  5.     mFDs = (pollfd *)calloc(1, sizeof(mFDs[0]));  
  6.     mDevices = (device_t **)calloc(1, sizeof(mDevices[0]));  
  7.     mFDs[0].events = POLLIN;  
  8.     mFDs[0].revents = 0;  
  9.     mDevices[0] = NULL;  
  10.           ...  
  11.     // 上面有赋值device_path = "/dev/input"  
  12.     res = scanDir(device_path);  
  13.           ...  
  14.     return true;  
  15. }  


接着又绕到scanDir()里面,这个函数无非就是对/dev/input这个目录的每个文件执行openDevice(),后者才是真正干活的:

[cpp] view plaincopy
  1. int EventHub::openDevice(const char *deviceName) {  
  2.     int version;  
  3.     int fd;  
  4.     struct pollfd *new_mFDs;  
  5.     device_t **new_devices;  
  6.     char **new_device_names;  
  7.     char name[80];  
  8.     char location[80];  
  9.     char idstr[80];  
  10.     struct input_id id;  
  11.   
  12.     LOGV("Opening device: %s", deviceName);  
  13.   
  14.     AutoMutex _l(mLock);  
  15.     // 根据路径打开文件获取version, id, name等信息  
  16.     fd = open(deviceName, O_RDWR);  
  17.     if(fd < 0) ...  
  18.     if(ioctl(fd, EVIOCGVERSION, &version))   
  19.         ...  
  20.     if(ioctl(fd, EVIOCGID, &id))   
  21.         ...  
  22.     if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1)   
  23.         ...  
  24.     // check to see if the device is on our excluded list - 如果此设备在排除名单内,忽略它  
  25.     List<String8>::iterator iter = mExcludedDevices.begin();  
  26.     List<String8>::iterator end = mExcludedDevices.end();  
  27.     for ( ; iter != end; iter++) {  
  28.         ...  
  29.     }  
  30.     // 读取location, idstr等信息  
  31.     if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), &location) < 1)   
  32.         ...  
  33.     if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), &idstr) < 1)   
  34.         ...  
  35.     // 将设备文件设置为非阻塞  
  36.     if (fcntl(fd, F_SETFL, O_NONBLOCK))   
  37.         ...  
  38.     // 在mDeviceById数组中寻找“空位”,扩充mDeviceById的空间并把新device加到尾部  
  39.     int devid = 0;  
  40.     while (devid < mNumDevicesById) {  
  41.         if (mDevicesById[devid].device == NULL) {  
  42.             break;  
  43.         }  
  44.         devid++;  
  45.     }  
  46.     if (devid >= mNumDevicesById) {  
  47.         device_ent* new_devids = (device_ent*)realloc(mDevicesById,  
  48.                 sizeof(mDevicesById[0]) * (devid + 1));  
  49.         if (new_devids == NULL) {  
  50.             LOGE("out of memory");  
  51.             return -1;  
  52.         }  
  53.         mDevicesById = new_devids;  
  54.         mNumDevicesById = devid+1;  
  55.         mDevicesById[devid].device = NULL;  
  56.         mDevicesById[devid].seq = 0;  
  57.     }  
  58.   
  59.     mDevicesById[devid].seq = (mDevicesById[devid].seq+(1<<SEQ_SHIFT))&SEQ_MASK;  
  60.     if (mDevicesById[devid].seq == 0) {  
  61.         mDevicesById[devid].seq = 1<<SEQ_SHIFT;  
  62.     }  
  63.     // 为后面用poll()来获取kernel层上报的input event作准备  
  64.     new_mFDs = (pollfd*)realloc(mFDs, sizeof(mFDs[0]) * (mFDCount + 1));  
  65.     new_devices = (device_t**)realloc(mDevices, sizeof(mDevices[0]) * (mFDCount + 1));  
  66.     if (new_mFDs == NULL || new_devices == NULL) {  
  67.         LOGE("out of memory");  
  68.         return -1;  
  69.     }  
  70.     mFDs = new_mFDs;  
  71.     mDevices = new_devices;  
  72.   
  73.     device_t* device = new device_t(devid|mDevicesById[devid].seq, deviceName, name);  
  74.     if (device == NULL) {  
  75.         LOGE("out of memory");  
  76.         return -1;  
  77.     }  
  78.   
  79.     device->fd = fd;  
  80.     mFDs[mFDCount].fd = fd;  
  81.     mFDs[mFDCount].events = POLLIN;  
  82.     mFDs[mFDCount].revents = 0;  
  83.   
  84.     // Figure out the kinds of events the device reports.  
  85.     // 分辨本device的输入类型: keypad? touchscreen? gamepad?  
  86.     uint8_t key_bitmask[sizeof_bit_array(KEY_MAX + 1)];  
  87.     memset(key_bitmask, 0, sizeof(key_bitmask));  
  88.     // 测试本device是否为键盘,是的话把key_bitmask保存下来  
  89.     LOGV("Getting keys...");  
  90.     if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {  
  91.        ...  
  92.     }  
  93.     // 是否为轨迹球或鼠标  
  94.     // See if this is a trackball (or mouse).  
  95.     if (test_bit(BTN_MOUSE, key_bitmask)) {  
  96.         ...  
  97.     }  
  98.     // 是否为touchscreen,是否支持多点触摸  
  99.     // See if this is a touch pad.  
  100.     uint8_t abs_bitmask[sizeof_bit_array(ABS_MAX + 1)];  
  101.     memset(abs_bitmask, 0, sizeof(abs_bitmask));  
  102.     LOGV("Getting absolute controllers...");  
  103.     if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_bitmask)), abs_bitmask) >= 0) {  
  104.         ...  
  105.     }  
  106.   
  107. #ifdef EV_SW  
  108.     // 是否为switch设备,这个宏没有打开  
  109. #endif  
  110.     // 如果是键盘的话,加载keypad-layout,即/usr/keylayout/中的xxx.kl文件  
  111.     if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {  
  112.            ...  
  113.         status_t status = device->layoutMap->load(keylayoutFilename);  
  114.         if (status) {  
  115.             LOGE("Error %d loading key layout.", status);  
  116.         }  
  117.            ...  
  118.         // tell the world about the devname (the descriptive name) - 找一个首选keyboard出来  
  119.         if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) {  
  120.             // the built-in keyboard has a well-known device ID of 0,  
  121.             // this device better not go away.  
  122.             mHaveFirstKeyboard = true;  
  123.             mFirstKeyboardId = device->id;  
  124.             property_set("hw.keyboards.0.devname", name);  
  125.         } else {  
  126.             // ensure mFirstKeyboardId is set to -something-.  
  127.             if (mFirstKeyboardId == 0) {  
  128.                 mFirstKeyboardId = device->id;  
  129.             }  
  130.         }  
  131.         // 如果键盘有数字键,方向键,游戏控制键等特殊按钮,都一一标记到classes中  
  132.         if (hasKeycodeLocked(device, AKEYCODE_Q))   
  133.             ...  
  134.         if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&  
  135.                 hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&  
  136.                 hasKeycodeLocked(device, AKEYCODE_DPAD_LEFT) &&  
  137.                 hasKeycodeLocked(device, AKEYCODE_DPAD_RIGHT) &&  
  138.                 hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {  
  139.             device->classes |= INPUT_DEVICE_CLASS_DPAD;  
  140.         }  
  141.           
  142.         // See if this device has a gamepad.  
  143.         for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES)/sizeof(GAMEPAD_KEYCODES[0]); i++) {  
  144.             if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {  
  145.                 device->classes |= INPUT_DEVICE_CLASS_GAMEPAD;  
  146.                 break;  
  147.             }  
  148.         }  
  149.   
  150.         LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",  
  151.                 device->id, name, propName, keylayoutFilename);  
  152.     }  
  153.   
  154.     // 如果不知道这个device是啥类型,忽略之  
  155.     if (device->classes == 0) {  
  156.        ...  
  157.     }  
  158.   
  159.     // 加到mDevicesById和mOpeningDevices中,回头getEvent()会处理mOpenningDevices链表中的新增device  
  160.   
  161.     mDevicesById[devid].device = device;  
  162.     device->next = mOpeningDevices;  
  163.     mOpeningDevices = device;  
  164.     mDevices[mFDCount] = device;  
  165.   
  166.     mFDCount++;  
  167.     return 0;  
  168. }  



初始化折腾一番后,又回到了getEvent中来,getEvent除了在第一此进入需要加设备外,其主体就是一个大循环:

[cpp] view plaincopy
  1. bool EventHub::getEvent(RawEvent* outEvent)  
  2. {  
  3.       ....  
  4.   
  5.     // main loop here - 主循环体  
  6.     for (;;) {  
  7.         // Report any devices that had last been removed. - 当有设备从系统中移除时  
  8.         if (mClosingDevices != NULL) {  
  9.              ...  
  10.         }  
  11.   
  12.     // Report any devices that had last been added - 当有设备加入到系统中时  
  13.         if (mOpeningDevices != NULL) {  
  14.             device_t* device = mOpeningDevices;  
  15.             LOGV("Reporting device opened: id=0x%x, name=%s\n",  
  16.                  device->id, device->path.string());  
  17.             mOpeningDevices = device->next;  
  18.             if (device->id == mFirstKeyboardId) {  
  19.                 outEvent->deviceId = 0;  
  20.             } else {  
  21.                 outEvent->deviceId = device->id;  
  22.             }  
  23.             outEvent->type = DEVICE_ADDED;  
  24.             outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);  
  25.             mNeedToSendFinishedDeviceScan = true;  
  26.             return true// 一个设备上报一个DEVICE_ADDED事件  
  27.         }  
  28.   
  29.     // After finish scanning all input devices in system, send finished siganal at boot time   
  30.         if (mNeedToSendFinishedDeviceScan) {  
  31.             mNeedToSendFinishedDeviceScan = false;  
  32.             outEvent->type = FINISHED_DEVICE_SCAN;  
  33.             outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);  
  34.             return true;  
  35.         }  
  36.   
  37.         // 下面为普通event获取和上报过程  
  38.              ... ...  
  39.     }  
  40. }  

从上面的代码段可知,对于mOpeningDevices中的device,getEvent()调用都是每读取一个马上上报DEVICE_ADDED事件并返回。所以如果我们的系统中有一个keypad和一个touchscreen,则在扫描阶段就会有3次getEvent()返回:键盘的DEVICE_ADDED,触摸屏的DEVICE_ADDED和表示扫描完成的FINISHED_DEVICE_SCAN。


原创粉丝点击