Android6.0 按键流程 读取设备事件(一)

来源:互联网 发布:学化妆的软件 编辑:程序博客网 时间:2024/05/21 10:00


一、初始化

InputManagerService在SystemServer中新建,然后调用了start函数,这里我们就不讲了,从InputManagerService的构造函数讲起。


[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public InputManagerService(Context context) {  
  2.     this.mContext = context;  
  3.     this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());  
  4.   
  5.     mUseDevInputEventForAudioJack =  
  6.             context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);  
  7.     Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="  
  8.             + mUseDevInputEventForAudioJack);  
  9.     mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());  
  10.   
  11.     LocalServices.addService(InputManagerInternal.classnew LocalService());  
  12. }  

nativeInit在com_android_server_input_InputManagerService.cpp中,实现如下:

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. static jlong nativeInit(JNIEnv* env, jclass /* clazz */,  
  2.         jobject serviceObj, jobject contextObj, jobject messageQueueObj) {  
  3.     sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);  
  4.     if (messageQueue == NULL) {  
  5.         jniThrowRuntimeException(env, "MessageQueue is not initialized.");  
  6.         return 0;  
  7.     }  
  8.   
  9.     NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,  
  10.             messageQueue->getLooper());  
  11.     im->incStrong(0);  
  12.     return reinterpret_cast<jlong>(im);  
  13. }  

新建了一个NativeInputManager对象,并且把这个对象返回了保存在了InputManagerService的mPtr对象中,这只是保存了c层对象的地址,所以只要使用long保存地址就行了。

下面我们看下其构造函数:

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. NativeInputManager::NativeInputManager(jobject contextObj,  
  2.         jobject serviceObj, const sp<Looper>& looper) :  
  3.         mLooper(looper), mInteractive(true) {  
  4.     JNIEnv* env = jniEnv();  
  5.   
  6.     mContextObj = env->NewGlobalRef(contextObj);  
  7.     mServiceObj = env->NewGlobalRef(serviceObj);  
  8.   
  9.     {  
  10.         AutoMutex _l(mLock);  
  11.         mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;  
  12.         mLocked.pointerSpeed = 0;  
  13.         mLocked.pointerGesturesEnabled = true;  
  14.         mLocked.showTouches = false;  
  15.     }  
  16.     mInteractive = true;  
  17.   
  18.     sp<EventHub> eventHub = new EventHub();  
  19.     mInputManager = new InputManager(eventHub, thisthis);  
  20. }  

新建了一个InputManager和EventHub。


InputManager对象是在InputManager.cpp文件中

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. InputManager::InputManager(  
  2.         const sp<EventHubInterface>& eventHub,  
  3.         const sp<InputReaderPolicyInterface>& readerPolicy,  
  4.         const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {  
  5.     mDispatcher = new InputDispatcher(dispatcherPolicy);  
  6.     mReader = new InputReader(eventHub, readerPolicy, mDispatcher);  
  7.     initialize();  
  8. }  

InputManager中新建了一个InputDispatcher和InputReader两个对象,然后调用了initialize函数:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. void InputManager::initialize() {  
  2.     mReaderThread = new InputReaderThread(mReader);  
  3.     mDispatcherThread = new InputDispatcherThread(mDispatcher);  
  4. }  

这两个变量就是两个线程我们就不看其构造函数了。


接着在InputManagerService中又调了start函数:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public void start() {  
  2.     Slog.i(TAG, "Starting input manager");  
  3.     nativeStart(mPtr);  
  4.   
  5.     // Add ourself to the Watchdog monitors.  
  6.     Watchdog.getInstance().addMonitor(this);  
  7.   
  8.     registerPointerSpeedSettingObserver();  
  9.     registerShowTouchesSettingObserver();  
  10.   
  11.     mContext.registerReceiver(new BroadcastReceiver() {  
  12.         @Override  
  13.         public void onReceive(Context context, Intent intent) {  
  14.             updatePointerSpeedFromSettings();  
  15.             updateShowTouchesFromSettings();  
  16.         }  
  17.     }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);  
  18.   
  19.     updatePointerSpeedFromSettings();  
  20.     updateShowTouchesFromSettings();  
  21. }  

我们主要看下nativeStart函数:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {  
  2.     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);  
  3.   
  4.     status_t result = im->getInputManager()->start();  
  5.     if (result) {  
  6.         jniThrowRuntimeException(env, "Input manager could not be started.");  
  7.     }  
  8. }  

我们先把InputManagerService保存的mPtr传下来的变量强制转成NativeInputManager,调用调用器getInputManager函数,也就是其InputManager的start函数

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. status_t InputManager::start() {  
  2.     status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);  
  3.     if (result) {  
  4.         ALOGE("Could not start InputDispatcher thread due to error %d.", result);  
  5.         return result;  
  6.     }  
  7.   
  8.     result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);  
  9.     if (result) {  
  10.         ALOGE("Could not start InputReader thread due to error %d.", result);  
  11.   
  12.         mDispatcherThread->requestExit();  
  13.         return result;  
  14.     }  
  15.   
  16.     return OK;  
  17. }  


二、EventHub

在上一节中,在NativeInputManager构造函数中,还新建了一个EventHub对象,下面我们就来介绍下:

我们先来分析下其构造函数:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. EventHub::EventHub(void) :  
  2.         mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),  
  3.         mOpeningDevices(0), mClosingDevices(0),  
  4.         mNeedToSendFinishedDeviceScan(false),  
  5.         mNeedToReopenDevices(false), mNeedToScanDevices(true),  
  6.         mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {  
  7.     acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);  
  8.   
  9.     mEpollFd = epoll_create(EPOLL_SIZE_HINT);  
  10.     LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance.  errno=%d", errno);  
  11.   
  12.     mINotifyFd = inotify_init();//INotify机制  
  13.     int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);//监控dev/input目录  
  14.     LOG_ALWAYS_FATAL_IF(result < 0, "Could not register INotify for %s.  errno=%d",  
  15.             DEVICE_PATH, errno);  
  16.   
  17.     struct epoll_event eventItem;  
  18.     memset(&eventItem, 0, sizeof(eventItem));  
  19.     eventItem.events = EPOLLIN;  
  20.     eventItem.data.u32 = EPOLL_ID_INOTIFY;  
  21.     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);//将这个iNotify的fd加入epoll  
  22.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance.  errno=%d", errno);  
  23.   
  24.     int wakeFds[2];  
  25.     result = pipe(wakeFds);//创建了管道,用来唤醒epoll  
  26.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);  
  27.   
  28.     mWakeReadPipeFd = wakeFds[0];  
  29.     mWakeWritePipeFd = wakeFds[1];  
  30.   
  31.     result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);  
  32.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",  
  33.             errno);  
  34.   
  35.     result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);  
  36.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",  
  37.             errno);  
  38.   
  39.     eventItem.data.u32 = EPOLL_ID_WAKE;  
  40.     result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);  
  41.     LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",  
  42.             errno);  
  43.   
  44.     int major, minor;  
  45.     getLinuxRelease(&major, &minor);  
  46.     // EPOLLWAKEUP was introduced in kernel 3.5  
  47.     mUsingEpollWakeup = major > 3 || (major == 3 && minor >= 5);  
  48. }  

在构造函数中,使用了INotify机制(在之前的博客中介绍过)监控dev/input下文件的创建和删除动作,并且将INotify的fd加入epoll机制。还创建了一个pipe,将read端的fd加入了epoll,用来唤醒epoll。

下面我们先来提下会在InputReaderThread这个线程中,不断调用InputReader的loopOnce函数,这个函数会调用EventHub的getEvents函数,我们先来分析下这个函数,其他的我们后续再分析,这个函数写的非常经典。

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {  
  2.     ALOG_ASSERT(bufferSize >= 1);  
  3.   
  4.     AutoMutex _l(mLock);  
  5.   
  6.     struct input_event readBuffer[bufferSize];  
  7.   
  8.     RawEvent* event = buffer;  
  9.     size_t capacity = bufferSize;  
  10.     bool awoken = false;  
  11.     for (;;) {  
  12.         ......  
  13.   
  14.         if (mNeedToScanDevices) {//这个变量第一次传进来为 true  
  15.             mNeedToScanDevices = false;  
  16.             scanDevicesLocked();//扫描设备  
  17.             mNeedToSendFinishedDeviceScan = true;  
  18.         }  

scanDevicesLocked函数调用了scanDirLocked函数

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. void EventHub::scanDevicesLocked() {  
  2.     status_t res = scanDirLocked(DEVICE_PATH);//dev/input  
  3.     if(res < 0) {  
  4.         ALOGE("scan dir failed for %s\n", DEVICE_PATH);  
  5.     }  
  6.     if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {  
  7.         createVirtualKeyboardLocked();  
  8.     }  
  9. }  

调用了scanDirLocked函数扫描dev/input下的所有设备,然后调用openDeviceLocked函数

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. status_t EventHub::scanDirLocked(const char *dirname)  
  2. {  
  3.     char devname[PATH_MAX];  
  4.     char *filename;  
  5.     DIR *dir;  
  6.     struct dirent *de;  
  7.     dir = opendir(dirname);  
  8.     if(dir == NULL)  
  9.         return -1;  
  10.     strcpy(devname, dirname);  
  11.     filename = devname + strlen(devname);  
  12.     *filename++ = '/';  
  13.     while((de = readdir(dir))) {  
  14.         if(de->d_name[0] == '.' &&  
  15.            (de->d_name[1] == '\0' ||  
  16.             (de->d_name[1] == '.' && de->d_name[2] == '\0')))  
  17.             continue;  
  18.         strcpy(filename, de->d_name);  
  19.         openDeviceLocked(devname);//打开设备  
  20.     }  
  21.     closedir(dir);  
  22.     return 0;  
  23. }  

openDeviceLocked函数,使用ioctrl获取设备的各种参数,将设备加入epoll,其data.u32设为deviceId,然后将设备入mDevices

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. status_t EventHub::openDeviceLocked(const char *devicePath) {  
  2.     char buffer[80];  
  3.   
  4.     ALOGV("Opening device: %s", devicePath);  
  5.   
  6.     int fd = open(devicePath, O_RDWR | O_CLOEXEC);  
  7.     if(fd < 0) {  
  8.         ALOGE("could not open %s, %s\n", devicePath, strerror(errno));  
  9.         return -1;  
  10.     }  
  11.   
  12.     ......//调用ioctl,获取device的各种参数  
  13.     eventItem.data.u32 = deviceId;//  
  14.     if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {//加入epoll  
  15.         ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);  
  16.         delete device;  
  17.         return -1;  
  18.     }  
  19.   
  20.     ......  
  21.   
  22.     addDeviceLocked(device);//加入mDevices  
  23.     return 0;  
  24. }  

继续分析我们的getEvents函数,分析while循环

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. bool deviceChanged = false;  
  2. while (mPendingEventIndex < mPendingEventCount) {  
  3.     const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];  
  4.     if (eventItem.data.u32 == EPOLL_ID_INOTIFY) {  
  5.         if (eventItem.events & EPOLLIN) {//notify监测到有新设备,或者设备拔出  
  6.             mPendingINotify = true;  
  7.         } else {  
  8.             ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);  
  9.         }  
  10.         continue;//跳出循环  
  11.     }  
  12.   
  13.     if (eventItem.data.u32 == EPOLL_ID_WAKE) {  
  14.         if (eventItem.events & EPOLLIN) {//唤醒事件  
  15.             ALOGV("awoken after wake()");  
  16.             awoken = true;//置位  
  17.             char buffer[16];  
  18.             ssize_t nRead;  
  19.             do {  
  20.                 nRead = read(mWakeReadPipeFd, buffer, sizeof(buffer));  
  21.             } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(buffer));  
  22.         } else {  
  23.             ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",  
  24.                     eventItem.events);  
  25.         }  
  26.         continue;  
  27.     }  

下面分析循环中的最后一段,这边是各种设备的事件

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1.     ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);//deviceId  
  2.     if (deviceIndex < 0) {  
  3.         ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.",  
  4.                 eventItem.events, eventItem.data.u32);  
  5.         continue;  
  6.     }  
  7.   
  8.     Device* device = mDevices.valueAt(deviceIndex);//填充event的值  
  9.     if (eventItem.events & EPOLLIN) {  
  10.         int32_t readSize = read(device->fd, readBuffer,  
  11.                 sizeof(struct input_event) * capacity);  
  12.         if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {  
  13.             // Device was removed before INotify noticed.  
  14.             ALOGW("could not get event, removed? (fd: %d size: %" PRId32  
  15.                     " bufferSize: %zu capacity: %zu errno: %d)\n",  
  16.                     device->fd, readSize, bufferSize, capacity, errno);  
  17.             deviceChanged = true;  
  18.             closeDeviceLocked(device);  
  19.         } else if (readSize < 0) {  
  20.             if (errno != EAGAIN && errno != EINTR) {  
  21.                 ALOGW("could not get event (errno=%d)", errno);  
  22.             }  
  23.         } else if ((readSize % sizeof(struct input_event)) != 0) {  
  24.             ALOGE("could not get event (wrong size: %d)", readSize);  
  25.         } else {  
  26.             int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;  
  27.   
  28.             size_t count = size_t(readSize) / sizeof(struct input_event);  
  29.             for (size_t i = 0; i < count; i++) {  
  30.                 struct input_event& iev = readBuffer[i];  
  31.                 ALOGV("%s got: time=%d.%06d, type=%d, code=%d, value=%d",  
  32.                         device->path.string(),  
  33.                         (int) iev.time.tv_sec, (int) iev.time.tv_usec,  
  34.                         iev.type, iev.code, iev.value);  
  35.   
  36.                 // Some input devices may have a better concept of the time  
  37.                 // when an input event was actually generated than the kernel  
  38.                 // which simply timestamps all events on entry to evdev.  
  39.                 // This is a custom Android extension of the input protocol  
  40.                 // mainly intended for use with uinput based device drivers.  
  41.                 if (iev.type == EV_MSC) {  
  42.                     if (iev.code == MSC_ANDROID_TIME_SEC) {  
  43.                         device->timestampOverrideSec = iev.value;  
  44.                         continue;  
  45.                     } else if (iev.code == MSC_ANDROID_TIME_USEC) {  
  46.                         device->timestampOverrideUsec = iev.value;  
  47.                         continue;  
  48.                     }  
  49.                 }  
  50.                 if (device->timestampOverrideSec || device->timestampOverrideUsec) {  
  51.                     iev.time.tv_sec = device->timestampOverrideSec;  
  52.                     iev.time.tv_usec = device->timestampOverrideUsec;  
  53.                     if (iev.type == EV_SYN && iev.code == SYN_REPORT) {  
  54.                         device->timestampOverrideSec = 0;  
  55.                         device->timestampOverrideUsec = 0;  
  56.                     }  
  57.                     ALOGV("applied override time %d.%06d",  
  58.                             int(iev.time.tv_sec), int(iev.time.tv_usec));  
  59.                 }  
  60.   
  61.                 // Use the time specified in the event instead of the current time  
  62.                 // so that downstream code can get more accurate estimates of  
  63.                 // event dispatch latency from the time the event is enqueued onto  
  64.                 // the evdev client buffer.  
  65.                 //  
  66.                 // The event's timestamp fortuitously uses the same monotonic clock  
  67.                 // time base as the rest of Android.  The kernel event device driver  
  68.                 // (drivers/input/evdev.c) obtains timestamps using ktime_get_ts().  
  69.                 // The systemTime(SYSTEM_TIME_MONOTONIC) function we use everywhere  
  70.                 // calls clock_gettime(CLOCK_MONOTONIC) which is implemented as a  
  71.                 // system call that also queries ktime_get_ts().  
  72.                 event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL  
  73.                         + nsecs_t(iev.time.tv_usec) * 1000LL;  
  74.                 ALOGV("event time %" PRId64 ", now %" PRId64, event->when, now);  
  75.   
  76.                 // Bug 7291243: Add a guard in case the kernel generates timestamps  
  77.                 // that appear to be far into the future because they were generated  
  78.                 // using the wrong clock source.  
  79.                 //  
  80.                 // This can happen because when the input device is initially opened  
  81.                 // it has a default clock source of CLOCK_REALTIME.  Any input events  
  82.                 // enqueued right after the device is opened will have timestamps  
  83.                 // generated using CLOCK_REALTIME.  We later set the clock source  
  84.                 // to CLOCK_MONOTONIC but it is already too late.  
  85.                 //  
  86.                 // Invalid input event timestamps can result in ANRs, crashes and  
  87.                 // and other issues that are hard to track down.  We must not let them  
  88.                 // propagate through the system.  
  89.                 //  
  90.                 // Log a warning so that we notice the problem and recover gracefully.  
  91.                 if (event->when >= now + 10 * 1000000000LL) {  
  92.                     // Double-check.  Time may have moved on.  
  93.                     nsecs_t time = systemTime(SYSTEM_TIME_MONOTONIC);  
  94.                     if (event->when > time) {  
  95.                         ALOGW("An input event from %s has a timestamp that appears to "  
  96.                                 "have been generated using the wrong clock source "  
  97.                                 "(expected CLOCK_MONOTONIC): "  
  98.                                 "event time %" PRId64 ", current time %" PRId64  
  99.                                 ", call time %" PRId64 ".  "  
  100.                                 "Using current time instead.",  
  101.                                 device->path.string(), event->when, time, now);  
  102.                         event->when = time;  
  103.                     } else {  
  104.                         ALOGV("Event time is ok but failed the fast path and required "  
  105.                                 "an extra call to systemTime: "  
  106.                                 "event time %" PRId64 ", current time %" PRId64  
  107.                                 ", call time %" PRId64 ".",  
  108.                                 event->when, time, now);  
  109.                     }  
  110.                 }  
  111.                 event->deviceId = deviceId;  
  112.                 event->type = iev.type;  
  113.                 event->code = iev.code;  
  114.                 event->value = iev.value;  
  115.                 event += 1;  
  116.                 capacity -= 1;  
  117.             }  
  118.             if (capacity == 0) {  
  119.                 // The result buffer is full.  Reset the pending event index  
  120.                 // so we will try to read the device again on the next iteration.  
  121.                 mPendingEventIndex -= 1;  
  122.                 break;  
  123.             }  
  124.         }  
  125.     } else if (eventItem.events & EPOLLHUP) {  
  126.         ALOGI("Removing device %s due to epoll hang-up event.",  
  127.                 device->identifier.name.string());  
  128.         deviceChanged = true;  
  129.         closeDeviceLocked(device);  
  130.     } else {  
  131.         ALOGW("Received unexpected epoll event 0x%08x for device %s.",  
  132.                 eventItem.events, device->identifier.name.string());  
  133.     }  
  134. }  

上面就是各种设备的事件处理,将event填充。

继续分析:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {//前面扫描到设备的添加或者删除  
  2.     mPendingINotify = false;  
  3.     readNotifyLocked();  
  4.     deviceChanged = true;  
  5. }  
  6.   
  7. // Report added or removed devices immediately.  
  8. if (deviceChanged) {//如果设备改变了,添加或者删除设备了,就要重新循环  
  9.     continue;  
  10. }  
readNotifyLocked函数,就是读取INotify的内容,然后执行相应的打开设备或者关闭设备。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. status_t EventHub::readNotifyLocked() {  
  2.     int res;  
  3.     char devname[PATH_MAX];  
  4.     char *filename;  
  5.     char event_buf[512];  
  6.     int event_size;  
  7.     int event_pos = 0;  
  8.     struct inotify_event *event;  
  9.   
  10.     ALOGV("EventHub::readNotify nfd: %d\n", mINotifyFd);  
  11.     res = read(mINotifyFd, event_buf, sizeof(event_buf));  
  12.     if(res < (int)sizeof(*event)) {  
  13.         if(errno == EINTR)  
  14.             return 0;  
  15.         ALOGW("could not get event, %s\n", strerror(errno));  
  16.         return -1;  
  17.     }  
  18.     //printf("got %d bytes of event information\n", res);  
  19.   
  20.     strcpy(devname, DEVICE_PATH);  
  21.     filename = devname + strlen(devname);  
  22.     *filename++ = '/';  
  23.   
  24.     while(res >= (int)sizeof(*event)) {  
  25.         event = (struct inotify_event *)(event_buf + event_pos);  
  26.         //printf("%d: %08x \"%s\"\n", event->wd, event->mask, event->len ? event->name : "");  
  27.         if(event->len) {  
  28.             strcpy(filename, event->name);  
  29.             if(event->mask & IN_CREATE) {  
  30.                 openDeviceLocked(devname);//打开设备  
  31.             } else {  
  32.                 ALOGI("Removing device '%s' due to inotify event\n", devname);  
  33.                 closeDeviceByPathLocked(devname);//关闭设备  
  34.             }  
  35.         }  
  36.         event_size = sizeof(*event) + event->len;  
  37.         res -= event_size;  
  38.         event_pos += event_size;  
  39.     }  
  40.     return 0;  
  41. }  
再分析getEvents的最后一部分
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1.     // Return now if we have collected any events or if we were explicitly awoken.  
  2.     if (event != buffer || awoken) {//这个event != buffer代表已经读取到内容了,所以event指针向前走了  
  3.         break;  
  4.     }  
  5.   
  6.     // Poll for events.  Mind the wake lock dance!  
  7.     // We hold a wake lock at all times except during epoll_wait().  This works due to some  
  8.     // subtle choreography.  When a device driver has pending (unread) events, it acquires  
  9.     // a kernel wake lock.  However, once the last pending event has been read, the device  
  10.     // driver will release the kernel wake lock.  To prevent the system from going to sleep  
  11.     // when this happens, the EventHub holds onto its own user wake lock while the client  
  12.     // is processing events.  Thus the system can only sleep if there are no events  
  13.     // pending or currently being processed.  
  14.     //  
  15.     // The timeout is advisory only.  If the device is asleep, it will not wake just to  
  16.     // service the timeout.  
  17.     mPendingEventIndex = 0;  
  18.   
  19.     mLock.unlock(); // release lock before poll, must be before release_wake_lock  
  20.     release_wake_lock(WAKE_LOCK_ID);  
  21.   
  22.     int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);//epoll等待,数据加入mPendingEventItems  
  23.   
  24.     acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);  
  25.     mLock.lock(); // reacquire lock after poll, must be after acquire_wake_lock  
  26.   
  27.     if (pollResult == 0) {  
  28.         // Timed out.  
  29.         mPendingEventCount = 0;  
  30.         break;  
  31.     }  
  32.   
  33.     if (pollResult < 0) {  
  34.         // An error occurred.  
  35.         mPendingEventCount = 0;  
  36.   
  37.         // Sleep after errors to avoid locking up the system.  
  38.         // Hopefully the error is transient.  
  39.         if (errno != EINTR) {  
  40.             ALOGW("poll failed (errno=%d)\n", errno);  
  41.             usleep(100000);  
  42.         }  
  43.     } else {  
  44.         // Some events occurred.  
  45.         mPendingEventCount = size_t(pollResult);  
  46.     }  
  47. }  
  48.   
  49. // All done, return the number of events we read.  
  50. return event - buffer;//返回个数  

当读取到内容或者需要唤醒时,直接退出。epoll将内容放入mPendingEventItems,等下次循环处理。
这样EventHub就分析结束了。

三、InputReader中的InputMapper

InputReader,前面分析到InputManagerService调用Start函数后,会在InputManager对象中,开启InputReaderThread,和InputDispatcherThread线程。

我们先来分析InputReaderThread,在一直调用InputReader的loopOnce函数

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. void InputReader::loopOnce() {  
  2.     ......  
  3.     size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);  
  4.   
  5.     { // acquire lock  
  6.         AutoMutex _l(mLock);  
  7.         mReaderIsAliveCondition.broadcast();  
  8.   
  9.         if (count) {  
  10.             processEventsLocked(mEventBuffer, count);  
  11.         }  

我们这边主要分析两个函数,先从EventHub中获取事件,然后调用processEventsLocked函数:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {  
  2.     for (const RawEvent* rawEvent = rawEvents; count;) {  
  3.         int32_t type = rawEvent->type;  
  4.         size_t batchSize = 1;  
  5.         if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {  
  6.             int32_t deviceId = rawEvent->deviceId;  
  7.             while (batchSize < count) {  
  8.                 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT  
  9.                         || rawEvent[batchSize].deviceId != deviceId) {  
  10.                     break;  
  11.                 }  
  12.                 batchSize += 1;  
  13.             }  
  14. #if DEBUG_RAW_EVENTS  
  15.             ALOGD("BatchSize: %d Count: %d", batchSize, count);  
  16. #endif  
  17.             processEventsForDeviceLocked(deviceId, rawEvent, batchSize);//设备事件  
  18.         } else {  
  19.             switch (rawEvent->type) {  
  20.             case EventHubInterface::DEVICE_ADDED://设备增加  
  21.                 addDeviceLocked(rawEvent->when, rawEvent->deviceId);  
  22.                 break;  
  23.             case EventHubInterface::DEVICE_REMOVED://设备移除  
  24.                 removeDeviceLocked(rawEvent->when, rawEvent->deviceId);  
  25.                 break;  
  26.             case EventHubInterface::FINISHED_DEVICE_SCAN:  
  27.                 handleConfigurationChangedLocked(rawEvent->when);  
  28.                 break;  
  29.             default:  
  30.                 ALOG_ASSERT(false); // can't happen  
  31.                 break;  
  32.             }  
  33.         }  
  34.         count -= batchSize;  
  35.         rawEvent += batchSize;  
  36.     }  
  37. }  
我们先来看下设备增加,会在mDevices中增加一个设备。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {  
  2.     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);  
  3.     if (deviceIndex >= 0) {  
  4.         ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);  
  5.         return;  
  6.     }  
  7.   
  8.     InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);  
  9.     uint32_t classes = mEventHub->getDeviceClasses(deviceId);  
  10.     int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);  
  11.   
  12.     InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);//创建一个InputDevice  
  13.     device->configure(when, &mConfig, 0);  
  14.     device->reset(when);  
  15.   
  16.     if (device->isIgnored()) {  
  17.         ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,  
  18.                 identifier.name.string());  
  19.     } else {  
  20.         ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,  
  21.                 identifier.name.string(), device->getSources());  
  22.     }  
  23.   
  24.     mDevices.add(deviceId, device);  
  25.     bumpGenerationLocked();  
  26.   
  27.     if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {  
  28.         notifyExternalStylusPresenceChanged();  
  29.     }  
  30. }  

我们来看看EventHub->getDeviceClasses函数

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. uint32_t EventHub::getDeviceClasses(int32_t deviceId) const {  
  2.     AutoMutex _l(mLock);  
  3.     Device* device = getDeviceLocked(deviceId);  
  4.     if (device == NULL) return 0;  
  5.     return device->classes;  
  6. }  

就是每个device的classed成员变量,那么我们还是要分析EventHub的openDeviceLocked函数:肯定是在ioctl获取各种参数的时候设置的这个成员变量:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. // joystick and gamepad buttons which are handled like keyboards for the most part.  
  2. bool haveKeyboardKeys = containsNonZeroByte(device->keyBitmask, 0, sizeof_bit_array(BTN_MISC))  
  3.         || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(KEY_OK),  
  4.                 sizeof_bit_array(KEY_MAX + 1));  
  5. bool haveGamepadButtons = containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_MISC),  
  6.                 sizeof_bit_array(BTN_MOUSE))  
  7.         || containsNonZeroByte(device->keyBitmask, sizeof_bit_array(BTN_JOYSTICK),  
  8.                 sizeof_bit_array(BTN_DIGI));  
  9. if (haveKeyboardKeys || haveGamepadButtons) {  
  10.     device->classes |= INPUT_DEVICE_CLASS_KEYBOARD;  
  11. }  
  12.   
  13. // See if this is a cursor device such as a trackball or mouse.  
  14. if (test_bit(BTN_MOUSE, device->keyBitmask)  
  15.         && test_bit(REL_X, device->relBitmask)  
  16.         && test_bit(REL_Y, device->relBitmask)) {  
  17.     device->classes |= INPUT_DEVICE_CLASS_CURSOR;  
  18. }  
  19.   
  20. // See if this is a touch pad.  
  21. // Is this a new modern multi-touch driver?  
  22. if (test_bit(ABS_MT_POSITION_X, device->absBitmask)  
  23.         && test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {  
  24.     // Some joysticks such as the PS3 controller report axes that conflict  
  25.     // with the ABS_MT range.  Try to confirm that the device really is  
  26.     // a touch screen.  
  27.     if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) {  
  28.         device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;  
  29.     }  
  30. // Is this an old style single-touch driver?  
  31. else if (test_bit(BTN_TOUCH, device->keyBitmask)  
  32.         && test_bit(ABS_X, device->absBitmask)  
  33.         && test_bit(ABS_Y, device->absBitmask)) {  
  34.     device->classes |= INPUT_DEVICE_CLASS_TOUCH;  
  35. // Is this a BT stylus?  
  36. else if ((test_bit(ABS_PRESSURE, device->absBitmask) ||  
  37.             test_bit(BTN_TOUCH, device->keyBitmask))  
  38.         && !test_bit(ABS_X, device->absBitmask)  
  39.         && !test_bit(ABS_Y, device->absBitmask)) {  
  40.     device->classes |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;  
  41.     // Keyboard will try to claim some of the buttons but we really want to reserve those so we  
  42.     // can fuse it with the touch screen data, so just take them back. Note this means an  
  43.     // external stylus cannot also be a keyboard device.  
  44.     device->classes &= ~INPUT_DEVICE_CLASS_KEYBOARD;  
  45. }  
  46.   
  47. // See if this device is a joystick.  
  48. // Assumes that joysticks always have gamepad buttons in order to distinguish them  
  49. // from other devices such as accelerometers that also have absolute axes.  
  50. if (haveGamepadButtons) {  
  51.     uint32_t assumedClasses = device->classes | INPUT_DEVICE_CLASS_JOYSTICK;  
  52.     for (int i = 0; i <= ABS_MAX; i++) {  
  53.         if (test_bit(i, device->absBitmask)  
  54.                 && (getAbsAxisUsage(i, assumedClasses) & INPUT_DEVICE_CLASS_JOYSTICK)) {  
  55.             device->classes = assumedClasses;  
  56.             break;  
  57.         }  
  58.     }  
  59. }  
  60.   
  61. // Check whether this device has switches.  
  62. for (int i = 0; i <= SW_MAX; i++) {  
  63.     if (test_bit(i, device->swBitmask)) {  
  64.         device->classes |= INPUT_DEVICE_CLASS_SWITCH;  
  65.         break;  
  66.     }  
  67. }  
结果果然是classes的设置,


那我们继续分析createDeviceLocked函数:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,  
  2.         const InputDeviceIdentifier& identifier, uint32_t classes) {  
  3.     InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),  
  4.             controllerNumber, identifier, classes);  
  5.   
  6.     // External devices.  
  7.     if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {  
  8.         device->setExternal(true);  
  9.     }  
  10.   
  11.     // Devices with mics.  
  12.     if (classes & INPUT_DEVICE_CLASS_MIC) {  
  13.         device->setMic(true);  
  14.     }  
  15.   
  16.     // Switch-like devices.  
  17.     if (classes & INPUT_DEVICE_CLASS_SWITCH) {  
  18.         device->addMapper(new SwitchInputMapper(device));  
  19.     }  
  20.   
  21.     // Vibrator-like devices.  
  22.     if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {  
  23.         device->addMapper(new VibratorInputMapper(device));  
  24.     }  
  25.   
  26.     // Keyboard-like devices.  
  27.     uint32_t keyboardSource = 0;  
  28.     int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;  
  29.     if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {  
  30.         keyboardSource |= AINPUT_SOURCE_KEYBOARD;  
  31.     }  
  32.     if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {  
  33.         keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;  
  34.     }  
  35.     if (classes & INPUT_DEVICE_CLASS_DPAD) {  
  36.         keyboardSource |= AINPUT_SOURCE_DPAD;  
  37.     }  
  38.     if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {  
  39.         keyboardSource |= AINPUT_SOURCE_GAMEPAD;  
  40.     }  
  41.   
  42.     if (keyboardSource != 0) {  
  43.         device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));  
  44.     }  
  45.   
  46.     // Cursor-like devices.  
  47.     if (classes & INPUT_DEVICE_CLASS_CURSOR) {  
  48.         device->addMapper(new CursorInputMapper(device));  
  49.     }  
  50.   
  51.     // Touchscreens and touchpad devices.  
  52.     if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {  
  53.         device->addMapper(new MultiTouchInputMapper(device));  
  54.     } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {  
  55.         device->addMapper(new SingleTouchInputMapper(device));  
  56.     }  
  57.   
  58.     // Joystick-like devices.  
  59.     if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {  
  60.         device->addMapper(new JoystickInputMapper(device));  
  61.     }  
  62.   
  63.     // External stylus-like devices.  
  64.     if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {  
  65.         device->addMapper(new ExternalStylusInputMapper(device));  
  66.     }  
  67.   
  68.     return device;  
  69. }  
这个函数又会根据classes不同,增加各种Mapper。


当我们在InputReader增加设备后,再来分析下processEventsForDeviceLocked函数,处理设备事件的:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. void InputReader::processEventsForDeviceLocked(int32_t deviceId,  
  2.         const RawEvent* rawEvents, size_t count) {  
  3.     ssize_t deviceIndex = mDevices.indexOfKey(deviceId);  
  4.     if (deviceIndex < 0) {  
  5.         ALOGW("Discarding event for unknown deviceId %d.", deviceId);  
  6.         return;  
  7.     }  
  8.   
  9.     InputDevice* device = mDevices.valueAt(deviceIndex);  
  10.     if (device->isIgnored()) {  
  11.         //ALOGD("Discarding event for ignored deviceId %d.", deviceId);  
  12.         return;  
  13.     }  
  14.   
  15.     device->process(rawEvents, count);  
  16. }  

这个函数是获取相对应的device执行process函数:

[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
  1. void InputDevice::process(const RawEvent* rawEvents, size_t count) {  
  2.     // Process all of the events in order for each mapper.  
  3.     // We cannot simply ask each mapper to process them in bulk because mappers may  
  4.     // have side-effects that must be interleaved.  For example, joystick movement events and  
  5.     // gamepad button presses are handled by different mappers but they should be dispatched  
  6.     // in the order received.  
  7.     size_t numMappers = mMappers.size();  
  8.     for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {  
  9.   
  10.         if (mDropUntilNextSync) {  
  11.             if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {  
  12.                 mDropUntilNextSync = false;  
  13.             } else {  
  14.             }  
  15.         } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {  
  16.             mDropUntilNextSync = true;  
  17.             reset(rawEvent->when);  
  18.         } else {  
  19.             for (size_t i = 0; i < numMappers; i++) {  
  20.                 InputMapper* mapper = mMappers[i];  
  21.                 mapper->process(rawEvent);  
  22.             }  
  23.         }  
  24.     }  
  25. }  

最后遍历各个Event,然后遍历每个Device的InputMapper去执行其process函数。


序列图


0 0
原创粉丝点击