上篇文章讲的是内核层对HID触控数据的处理,本篇从framework层来看下触控数据的流向.以及我们在哪修改来适应公司的业务.
关于InputFliger网上详细的教程有很多,流程图,代码解析都有,大家可自己查阅下,下面只是从具体的调试和数据流程角度分析.
InputFliger个人理解整体分三大部分.一是EventHub.cpp,主要是从内核建立的节点获取设备描述符以及input数据.二是InputRead.cpp,主要是对EventHub.cpp获取的数据进行分析,整合.三是InputDispatcher.cpp,主要是把InputRead.cpp整合后的数据进行转发.
目录结构:frameworks/native/services/inputfliger
1.EventHub首先会打开/dev/hidraw*节点,来获取描述符,一定要看下路径是否正确,以及描述符是否是对的.
代码如下:1073行的open函数打开节点.然后通过ioctl函数获取描述符信息,很全,想要的数据个格式都在里面.
1068 status_t EventHub::openDeviceLocked(const char *devicePath) {
1069 char buffer[80];
1070
1071 ALOGV("Opening device: %s", devicePath);
1072
1073 int fd = open(devicePath, O_RDWR | O_CLOEXEC);
1074 if(fd < 0) {
1075 ALOGE("could not open %s, %s\n", devicePath, strerror(errno));
1076 return -1;
1077 }
1078
1079 InputDeviceIdentifier identifier;
1080
1081 // Get device name.
1082 if(ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
1083 //fprintf(stderr, "could not get device name for %s, %s\n", devicePath, strerror(errno));
1084 } else {
1085 buffer[sizeof(buffer) - 1] = '\0';
1086 identifier.name.setTo(buffer);
1087 }
1088
1089 // Check to see if the device is on our excluded list
1090 for (size_t i = 0; i < mExcludedDevices.size(); i++) {
1091 const String8& item = mExcludedDevices.itemAt(i);
1092 if (identifier.name == item) {
1093 ALOGI("ignoring event id %s driver %s\n", devicePath, item.string());
1094 close(fd);
1095 return -1;
1096 }
1097 }
1098
1099 // Get device driver version.
1100 int driverVersion;
1101 if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
1102 ALOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
1103 close(fd);
1104 return -1;
1105 }
1106
1107 // Get device identifier.
1108 struct input_id inputId;
1109 if(ioctl(fd, EVIOCGID, &inputId)) {
1110 ALOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
1111 close(fd);
1112 return -1;
1113 }
1114 identifier.bus = inputId.bustype;
1115 identifier.product = inputId.product;
1116 identifier.vendor = inputId.vendor;
1117 identifier.version = inputId.version;
1118
1145 // Allocate device. (The device object takes ownership of the fd at this point.)
1146 int32_t deviceId = mNextDeviceId++;
1147 Device* device = new Device(fd, deviceId, String8(devicePath), identifier);
1148
1149 ALOGV("add device %d: %s\n", deviceId, devicePath);
1150 ALOGV(" bus: %04x\n"
1151 " vendor %04x\n"
1152 " product %04x\n"
1153 " version %04x\n",
1154 identifier.bus, identifier.vendor, identifier.product, identifier.version);
1155 ALOGV(" name: \"%s\"\n", identifier.name.string());
1156 ALOGV(" location: \"%s\"\n", identifier.location.string());
1157 ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.string());
1158 ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.string());
1159 ALOGV(" driver: v%d.%d.%d\n",
1160 driverVersion >> 16, (driverVersion >> 8) & 0xff, driverVersion & 0xff);
1161
1162 // Load the configuration file for the device.
1163 loadConfigurationLocked(device);
log如下:
01-01 08:00:13.852 2825 2992 D EventHub: ###name: "MStar Smart TV Keypad"
01-01 08:00:13.900 2825 2992 D EventHub: ###bus: 24,vendor 13975, product 1,version 1
01-01 08:00:13.900 2825 2992 D EventHub: ###name: "MStar Smart TV IR Receiver"
01-01 08:00:13.912 2825 2992 D InputReader: #####swidth -1,sheight -1,nlwidth 1920,nlheight 1080 nwidht 1920 nheight 1080,npw 1920 nph 1080
01-01 08:00:13.912 2825 2992 D InputReader: ######Device reconfigured: id=1, name='Honghe F86H33+023', size 1920x1080, orientation 0, mode 1, display id 0,rawwidth 32768,rawheight 32768,verdor 2757,produce 10a
01-01 08:00:13.912 2825 2992 D InputReader: ##### scale 0.045776
然后通过getEvents()函数获取input数据,InputReader里面会拿到该数据,然后进行处理.
代码如下:
721 size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
722 ALOG_ASSERT(bufferSize >= 1);
723
724 AutoMutex _l(mLock);
725
726 struct input_event readBuffer[bufferSize];
727
728 RawEvent* event = buffer;
729 size_t capacity = bufferSize;
730 bool awoken = false;
731 for (;;) {
732 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
733
734 // Reopen input devices if needed.
735 if (mNeedToReopenDevices) {
736 mNeedToReopenDevices = false;
737
738 ALOGI("Reopening all input devices due to a configuration change.");
739
740 closeAllDevicesLocked();
741 mNeedToScanDevices = true;
742 break; // return to the caller before we
2.InputReader里面主要是对数据进行处理,大体逻辑如下:a.开启一个线程,通过EventHub->getEvents()获取input数据,然后通过id对应不同的mapper进行数据的处理.
代码如下:
a.loopOnce(),InputReader.cpp首先会跳到这里执行.360行从EventHub里面获取input数据.然后调用processEventsLocked()函数.
338 void InputReader::loopOnce() {
339 int32_t oldGeneration;
340 int32_t timeoutMillis;
341 bool inputDevicesChanged = false;
342 Vector<InputDeviceInfo> inputDevices;
343 { // acquire lock
344 AutoMutex _l(mLock);
345
346 oldGeneration = mGeneration;
347 timeoutMillis = -1;
348
349 uint32_t changes = mConfigurationChangesToRefresh;
350 if (changes) {
351 mConfigurationChangesToRefresh = 0;
352 timeoutMillis = 0;
353 refreshConfigurationLocked(changes);
354 } else if (mNextTimeout != LLONG_MAX) {
355 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
356 timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
357 }
358 } // release lock
359
360 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
361
362 { // acquire lock
363 AutoMutex _l(mLock);
364 mReaderIsAliveCondition.broadcast();
365
366 if (count) {
367 processEventsLocked(mEventBuffer, count);
368 }
369
b.processEventsLocked()函数如下:主要是调用processEventsForDeviceLocked()函数.
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
404 for (const RawEvent* rawEvent = rawEvents; count;) {
405 int32_t type = rawEvent->type;
406 size_t batchSize = 1;
407 if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
408 int32_t deviceId = rawEvent->deviceId;
409 while (batchSize < count) {
410 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
411 || rawEvent[batchSize].deviceId != deviceId) {
412 break;
413 }
414 batchSize += 1;
415 }
416 #if DEBUG_RAW_EVENTS
417 ALOGD("BatchSize: %d Count: %d", batchSize, count);
418 #endif
419 processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
c.processEventsForDeviceLocked()函数如下:最后主要是调用device-process()函数进行处理,其实是调用了InputDevice->process函数,1146行里面会通过for循环对不同的input事件进行处理,对与不同的设备InputReader.cpp有不同的process函数与之对应.
574 void InputReader::processEventsForDeviceLocked(int32_t deviceId,
575 const RawEvent* rawEvents, size_t count) {
576 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
577 if (deviceIndex < 0) {
578 ALOGW("Discarding event for unknown deviceId %d.", deviceId);
579 return;
580 }
581
582 InputDevice* device = mDevices.valueAt(deviceIndex);
583 if (device->isIgnored()) {
584 //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
585 return;
586 }
587
588 device->process(rawEvents, count);
589 }
1116 void InputDevice::process(const RawEvent* rawEvents, size_t count) {
1117 // Process all of the events in order for each mapper.
1118 // We cannot simply ask each mapper to process them in bulk because mappers may
1119 // have side-effects that must be interleaved. For example, joystick movement events and
1120 // gamepad button presses are handled by different mappers but they should be dispatched
1121 // in the order received.
1122 size_t numMappers = mMappers.size();
1123 for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
1124 #if DEBUG_RAW_EVENTS
1125 ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%lld",
1126 rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
1127 rawEvent->when);
1128 #endif
1129
1130 if (mDropUntilNextSync) {
1131 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
1132 mDropUntilNextSync = false;
1133 #if DEBUG_RAW_EVENTS
1134 ALOGD("Recovered from input event buffer overrun.");
1135 #endif
1136 } else {
1137 #if DEBUG_RAW_EVENTS
1138 ALOGD("Dropped input event while waiting for next input sync.");
1139 #endif
1140 }
1141 } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
1142 ALOGI("Detected input event buffer overrun for device %s.", getName().string());
1143 mDropUntilNextSync = true;
1144 reset(rawEvent->when);
1145 } else {
1146 for (size_t i = 0; i < numMappers; i++) {
1147 InputMapper* mapper = mMappers[i];
1148 mapper->process(rawEvent);
1149 }
1150 }
1151 }
1152 }
d.我这处理的主要是多点触控事件,所以要看MultiTouchInputMapper->process对应的处理.函数里面主要是TouchInputMapper->process();然后调用syncTouch()函数.MultiTouchInputMapper->syncTouch()为实际处理数据的地方,也就是我们需要修改的地方.
825 void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
6826 TouchInputMapper::process(rawEvent);
6827
6828 mMultiTouchMotionAccumulator.process(rawEvent);
6829 }
4193 void TouchInputMapper::sync(nsecs_t when) {
4194 const RawState* last = mRawStatesPending.isEmpty() ?
4195 &mCurrentRawState : &mRawStatesPending.top();
4196
4197 // Push a new state.
4198 mRawStatesPending.push();
4199 RawState* next = &mRawStatesPending.editTop();
4200 next->clear();
4201 next->when = when;
4202
4203 // Sync button state.
4204 next->buttonState = mTouchButtonAccumulator.getButtonState()
4205 | mCursorButtonAccumulator.getButtonState();
4206
4207 // Sync scroll
4208 next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
4209 next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
4210 mCursorScrollAccumulator.finishSync();
4211
4212 // Sync touch
4213 syncTouch(when, next);
...
831 void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
6832 size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
6833 size_t outCount = 0;
6834 BitSet32 newPointerIdBits;
6835 mHavePointerIds = true;
6836
6837 for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
6838 const MultiTouchMotionAccumulator::Slot* inSlot =
6839 mMultiTouchMotionAccumulator.getSlot(inIndex);
6840 if (!inSlot->isInUse()) {
6841 continue;
6842 }
6843
6844 if (outCount >= MAX_POINTERS) {
6845 #if DEBUG_POINTERS
6846 ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
6847 "ignoring the rest.",
6848 getDeviceName().string(), MAX_POINTERS);
6849 #endif
6850 break; // too many fingers!
6851 }
6852
6853 RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
6854 outPointer.x = inSlot->getX();
6855 outPointer.y = inSlot->getY();
6856 outPointer.pressure = inSlot->getPressure();
6857 outPointer.touchMajor = inSlot->getTouchMajor();
6858 outPointer.touchMinor = inSlot->getTouchMinor();
6859 outPointer.toolMajor = inSlot->getToolMajor();
6860 outPointer.toolMinor = inSlot->getToolMinor();
6861 outPointer.orientation = inSlot->getOrientation();
6862 outPointer.distance = inSlot->getDistance();
6863 outPointer.tiltX = 0;
6864 outPointer.tiltY = 0;
6865
6866 //ALOGD("##### touch major %ld,minor %ld, tool major %ld,minor %ld",outPointer.touchMajor,outPointer.touchMinor,outPointer.toolMajor,outPointer.toolMinor);
6867
e.在往下面的数据经过synctouch后,调用TouchInputMapper::sync()函数中的processRawToucher();该函数中通过cookAndDispatch()函数进行数据的dispatch了,这块就是一个标准流程,没啥需要处理的,感兴趣的可以自己看看.
4234 void TouchInputMapper::processRawTouches(bool timeout) {
4235 if (mDeviceMode == DEVICE_MODE_DISABLED) {
4236 // Drop all input if the device is disabled.
4237 mCurrentRawState.clear();
4238 mRawStatesPending.clear();
4239 return;
4240 }
4241
4242 // Drain any pending touch states. The invariant here is that the mCurrentRawState is always
4243 // valid and must go through the full cook and dispatch cycle. This ensures that anything
4244 // touching the current state will only observe the events that have been dispatched to the
4245 // rest of the pipeline.
4246 const size_t N = mRawStatesPending.size();
4247 size_t count;
4248 for(count = 0; count < N; count++) {
4249 const RawState& next = mRawStatesPending[count];
4250
4251 // A failure to assign the stylus id means that we're waiting on stylus data
4252 // and so should defer the rest of the pipeline.
4253 if (assignExternalStylusId(next, timeout)) {
4254 break;
4255 }
4256
4257 // All ready to go.
4258 clearStylusDataPendingFlags();
4259 mCurrentRawState.copyFrom(next);
4260 if (mCurrentRawState.when < mLastRawState.when) {
4261 mCurrentRawState.when = mLastRawState.when;
4262 }
4263 cookAndDispatch(mCurrentRawState.when);
4264 }
4265 if (count != 0) {
4266 mRawStatesPending.removeItemsAt(0, count);
4267 }
4268
log如下:
06-28 16:43:01.964 2797 2992 D InputReader: BatchSize: 7 Count: 7
06-28 16:43:01.964 2797 2992 D InputReader: Input event: device=2 type=0x0003 code=0x0039 value=0x00000007 when=2385905411000
06-28 16:43:01.964 2797 2992 D InputReader: Input event: device=2 type=0x0003 code=0x0035 value=0x000033bd when=2385905411000
06-28 16:43:01.964 2797 2992 D InputReader: Input event: device=2 type=0x0003 code=0x0036 value=0x000074d5 when=2385905411000
06-28 16:43:01.964 2797 2992 D InputReader: Input event: device=2 type=0x0001 code=0x014a value=0x00000001 when=2385905411000
06-28 16:43:01.964 2797 2992 D InputReader: Input event: device=2 type=0x0003 code=0x0000 value=0x000033bd when=2385905411000
06-28 16:43:01.964 2797 2992 D InputReader: Input event: device=2 type=0x0003 code=0x0001 value=0x000074d5 when=2385905411000
06-28 16:43:01.964 2797 2992 D InputReader: Input event: device=2 type=0x0000 code=0x0000 value=0x00000000 when=2385905411000
06-28 16:43:01.964 2797 2992 D InputReader: ##### touch major 68,minor 68, tool major 0,minor 0
06-28 16:43:01.964 2797 2992 D InputReader: syncTouch: pointerCount 0 -> 1, touching ids 0x00000000 -> 0x80000000, hovering ids 0x00000000 -> 0x00000000 ,touchmajar 68
06-28 16:43:01.964 2797 2992 D InputReader: line 4906
06-28 16:43:01.964 2797 2992 D InputReader: line 4944 toucMajor 0
06-28 16:43:01.964 2797 2992 D InputReader: line 4946 toucMajor 0
06-28 16:43:01.964 2797 2992 D InputReader: #####touchMajor 3.112793
06-28 16:43:01.964 2797 2992 D InputReader: #### next major68, last majro68
06-28 16:43:01.964 2797 2992 D InputDispatcher: notifyMotion - eventTime=2385905411000, deviceId=2, source=0x5002, policyFlags=0x0, action=0x0, actionButton=0x0, flags=0x0, metaState=0x0, buttonState=0x0,edgeFlags=0x0, xPrecision=17.066668, yPrecision=30.340740, downTime=2385905411000
06-28 16:43:01.964 2797 2992 D InputDispatcher: Pointer 0: id=0, toolType=1, x=776.074219, y=985.770264, pressure=1.000000, size=0.002075, touchMajor=3.112793, touchMinor=3.112793, toolMajor=3.112793, toolMinor=3.112793, orientation=0.000000
06-28 16:43:01.964 2797 2991 D InputDispatcher: Resetting ANR timeouts.
06-28 16:43:01.964 2797 2991 D InputDispatcher: dispatchMotion - eventTime=2385905411000, deviceId=2, source=0x5002, policyFlags=0x62000000, action=0x0, actionButton=0x0, flags=0x0, metaState=0x0, buttonState=0x0,edgeFlags=0x0, xPrecision=17.066668, yPrecision=30.340740, downTime=2385905411000
06-28 16:43:01.965 2797 2991 D InputDispatcher: Pointer 0: id=0, toolType=1, x=776.074219, y=985.770264, pressure=1.000000, size=0.002075, touchMajor=3.112793, touchMinor=3.112793, toolMajor=3.112793, toolMinor=3.112793, orientation=0.000000
06-28 16:43:01.965 2797 2991 D InputDispatcher: findTouchedWindow finished: injectionResult=0, injectionPermission=1, timeSpentWaitingForApplication=0.0ms
06-28 16:43:01.965 2797 2991 D InputDispatcher: dispatchEventToCurrentInputTargets