android4.0-input-touch - 图文

发布时间 : 星期六 文章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 = mLocked.pointerController.promote(); if (controller != NULL) {

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);

联系合同范文客服:xxxxx#qq.com(#替换为@)