发布时间 : 星期六 文章android4.0-input-touch - 图文更新完毕开始阅读
从下面开始就进入native空间
com_android_server_InputManager.cpp (frameworks\\base\\services\\jni)里面
nativeSetDisplaySize对应android_server_InputManager_nativeSetDisplaySize调用
gNativeInputManager->setDisplaySize(displayId, width, height, externalWidth, externalHeight); 在setDisplaySize里面判断
if (mLocked.displayWidth != width || mLocked.displayHeight != height) {
changed = true;
mLocked.displayWidth = width; mLocked.displayHeight = height;
sp
controller->setDisplaySize(width, height); } }
if (mLocked.displayExternalWidth != externalWidth
|| mLocked.displayExternalHeight != externalHeight) { changed = true;
mLocked.displayExternalWidth = externalWidth; mLocked.displayExternalHeight = externalHeight; } 如果这次设置的值和旧值相等,就什么也不做退出。如果不相等,设置changed = true,同时保存新的值 if (changed) {
mInputManager->getReader()->requestRefreshConfiguration( InputReaderConfiguration::CHANGE_DISPLAY_INFO);
}
如果值有变化,就调用inputreader刷新配置,提示是displayinfo改变
首先是去InputManager.cpp (frameworks\\base\\services\\input) 文件里面 getReader() return mReader; 这个就是InputManager创建是创建的inputreader
InputReader.cpp (frameworks\\base\\services\\input)里面 InputReader::requestRefreshConfiguration调用 if (changes) {
bool needWake = !mConfigurationChangesToRefresh; mConfigurationChangesToRefresh |= changes;
if (needWake) {
mEventHub->wake(); }
}
如果改变类型不为0,就mConfigurationChangesToRefresh取反送给needWake,mConfigurationChangesToRefresh表示需要改变配置的类型集合,初始化为0,因此needWake就为1,同时把改变类型与给mConfigurationChangesToRefresh,接着判断needWake,如果为1,就进入mEventHub的唤醒程序。
这段话意思就是如果有正在改变配置需求,就表明整个input系统正在运行,所以不需要唤醒。只需要把新的改变类型放在mConfigurationChangesToRefresh就行了,如果没有,那么input系统有可能在睡眠,为了快速响应改变,需要唤醒整个input系统。
EventHub.cpp (frameworks\\base\\services\\input)里面 EventHub::wake()调用
nWrite = write(mWakeWritePipeFd, \
直接向mWakeWritePipeFd管道里面写一个字符。前面2.5节讲到mWakeReadPipeFd已经被mEpollFd监控了,向mWakeWritePipeFd写就会引起mWakeReadPipeFd变化。在EventHub::getEvents里面就会执行if (eventItem.data.u32 == EPOLL_ID_WAKE)这个分支,设置awoken为true,当mPendingEventItems事件处理完,就会判断awoken,如果为true就立即结束循环,返回给inputreader进行处理。
至此,配置surface size执行部分结束了,但是size并没有真正配置到mExternalDisplay和mInternalDisplay里面,只是改变类型放在mConfigurationChangesToRefresh里面,真正的size还保存在NativeInputManager的mLocked里面 这时并没有输入事件或者设备变化发生,因此InputReader::loopOnce很快结束,进入下一次循环
InputReader::loopOnce 接着调用
uint32_t changes = mConfigurationChangesToRefresh; if (changes) {
mConfigurationChangesToRefresh = 0; refreshConfigurationLocked(changes); }
InputReader::refreshConfigurationLocked
mPolicy->getReaderConfiguration(&mConfig);
mPolicy就是NativeInputManager的对象,在创建inputreader传入的。 com_android_server_InputManager.cpp (frameworks\\base\\services\\jni)里面 NativeInputManager::getReaderConfiguration调用 { // acquire lock AutoMutex _l(mLock)
outConfig->setDisplayInfo(0, false /*external*/, mLocked.displayWidth, mLocked.displayHeight, mLocked.displayOrientation);
outConfig->setDisplayInfo(0, true /*external*/,
mLocked.displayExternalWidth, mLocked.displayExternalHeight, mLocked.displayOrientation);
} // release lock
outConfig就是inputreader里面的mConfig,因此调用 InputReaderConfiguration::setDisplayInfo if (displayId == 0) {
DisplayInfo& info = external ? mExternalDisplay : mInternalDisplay; info.width = width; info.height = height;
info.orientation = orientation;
}
看到没有,饶了一个大圈,这里才把surface size真正放在mExternalDisplay和 mInternalDisplay里面,供后面调用InputReaderConfiguration::getDisplayInfo时使用。
refreshConfigurationLocked函数会在inputreader创建时执行一次,但那个时候input device还没有创建,而且changes为0,因此不会执行下面的部分。
if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) { mEventHub->requestReopenDevices();
如果改变类型是reopen,就调用eventhub的requestReopenDevices
EventHub::requestReopenDevices里面设置mNeedToReopenDevices = true,这个会在EventHub::getEvents里面进行判断,前面2.6节已经讲了 } else {
for (size_t i = 0; i < mDevices.size(); i++) { InputDevice* device = mDevices.valueAt(i); device->configure(now, &mConfig, changes); } }
得到所有的device,循环调用每个device的configure去重新配置。 InputDevice::configure已经在InputReader::addDeviceLocked讲过了,刚开始第一次配置changes是0,表示需要全面的初始化。现在只需要配置改变的部分了。
至此,我们整个input touch的工作环境已经配置好了,就等有触摸事件发生然后处理了
2.7.3处理来自于事件驱动设备的事件
InputReader::processEventsForDeviceLocked,它负责处理来自于同一个设备且在mEventBuffer中连续的多个事件,其函数原型如下:
ssize_t deviceIndex = mDevices.indexOfKey(deviceId); if (deviceIndex < 0) {
LOGW(\ return; }
得到发生事件设备索引
InputDevice* device = mDevices.valueAt(deviceIndex); 根据索引得到发生事件的device if (device->isIgnored()) {
//LOGD(\ return; }
如果device没有mapper,就返回不做任何处理。
device->process(rawEvents, count); 调用process处理
InputDevice::process for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) 一次取出每一个事件 for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i]; mapper->process(rawEvent); }
对每一个事件都用这个device所有mapper进行处理
从上面的代码中可以看出,在InputDevice::process中,对于传入的每一个RawEvent,依次调用InputDevice中的每一个InputMapper来进行处理。前面提到过,InputDevice包含一组处理对应设备事件InputMapper,现在这些InputMapper开始干活了。
因为我们的touch只有一个SingleTouchInputMapper 这里先说说单点touch需要处理事件集合
代码:
input_report_abs(myInputDev, ABS_X, event->x); input_report_abs(myInputDev, ABS_Y, event->y); 产生的事件:*type, code, value EV_ABS,ABS_X,event->x
EV_ABS,ABS_Y,event->y 代码:
input_report_key(myInputDev, BTN_TOUCH, 1); 产生的事件:*type, code, value EV_KEY, BTN_TOUCH, 1 代码:
input_sync(myInputDev);
它调用input_event(dev, EV_SYN, SYN_REPORT, 0); 产生的事件:*type, code, value EV_SYN, SYN_REPORT, 0
SingleTouchInputMapper::process调用 TouchInputMapper::process(rawEvent); TouchInputMapper::process mCursorButtonAccumulator.process(rawEvent);