当前位置: 首页 > 工具软件 > EventHub > 使用案例 >

Android InputFliger流程分析,从内核 Hid到EventHub,InputRead,InputDispatcher(二)

扈沛
2023-12-01

上篇文章讲的是内核层对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
 

 类似资料: