【安卓13 源码】Input子系统(4)- InputReader 数据处理

1. 多指触控协议

多指触控协议有 2 种:

> A类: 处理无关联的接触: 用于直接发送原始数据;

> B类: 处理跟踪识别类的接触: 通过事件slot发送相关联的独立接触更新。

B协议可以使用一个ID来标识触点,可以减少上报到用户空间的数据量,这个ID(ABS_MT_TRACKING_ID)可以有硬件提供或者从原始数据计算而得。而InputReader 就是处理这些数据

通过下列命令可以dump :adb shell getevent -tl

[    1029.903648] /dev/input/event1: EV_SYN       0004                 00000405            
[    1029.903648] /dev/input/event1: EV_SYN       0005                 35c02ec5            
[    1029.903648] /dev/input/event1: EV_ABS       ABS_MT_SLOT          00000000           
[    1029.903648] /dev/input/event1: EV_ABS       ABS_MT_POSITION_X    00000173             第一个手指X坐标
[    1029.903648] /dev/input/event1: EV_ABS       ABS_MT_SLOT          00000001            
[    1029.903648] /dev/input/event1: EV_ABS       ABS_MT_POSITION_X    00000321             第二个手指X坐标
[    1029.903648] /dev/input/event1: EV_SYN       SYN_REPORT           00000000             

[    1031.902947] /dev/input/event1: EV_SYN       0004                 00000407            
[    1031.902947] /dev/input/event1: EV_SYN       0005                 35b8a020            
[    1031.902947] /dev/input/event1: EV_ABS       ABS_MT_SLOT          00000000            第一个手指有事件 
[    1031.902947] /dev/input/event1: EV_ABS       ABS_MT_TRACKING_ID   ffffffff            TRACKING_ID为-1代表第一个手指抬起消失
[    1031.902947] /dev/input/event1: EV_SYN       SYN_REPORT           00000000             
[    1032.024946] /dev/input/event1: EV_SYN       0004                 00000408            
[    1032.024946] /dev/input/event1: EV_SYN       0005                 016372d8            
[    1032.024946] /dev/input/event1: EV_ABS       ABS_MT_SLOT          00000001            第二个手指有事件  
[    1032.024946] /dev/input/event1: EV_ABS       ABS_MT_POSITION_Y    0000016c              第二个 Y坐标
[    1032.024946] /dev/input/event1: EV_SYN       SYN_REPORT           00000000             
[    1032.907686] /dev/input/event1: EV_SYN       0004                 00000408            
[    1032.907686] /dev/input/event1: EV_SYN       0005                 35ebac8c            
[    1032.907686] /dev/input/event1: EV_ABS       ABS_MT_TRACKING_ID   ffffffff            第二个手指消失抬起  
[    1032.907686] /dev/input/event1: EV_KEY       BTN_TOUCH            UP                  抬起
[    1032.907686] /dev/input/event1: EV_KEY       BTN_TOOL_FINGER      UP                  
[    1032.907686] /dev/input/event1: EV_SYN       SYN_REPORT           00000000   

其中分为 3 个类型,为 EV_SYN、EV_ABS 和 EV_KEY

0004:代表一个事件开始(不必要)

0005:代表一个事件开始(不必要)

SYN_REPORT:代表一个事件的结束 (必要)

ABS_MT_SLOT:

本质代表者不同手指,它的value代表手指id

ABS_MT_TRACKING_ID:

类型B特有的,实际上,每个slot会和一个ID相对应,一个非负数的表示一次接触,-1表示这是一个无用的slot(或者理解为一次接触的结束) 。

BTN_TOUCH

触碰按键。其值是DOWN或者UP。

2. InputReader 处理触摸数据

/frameworks/native/services/inputflinger/reader/InputReader.cpp

InputReader 监听设备的数据,getEvents()是阻塞的,只有当有事件或者被wake才会被唤醒向下执行。

86  void InputReader::loopOnce() {
87      int32_t oldGeneration;
88      int32_t timeoutMillis;
89      bool inputDevicesChanged = false;
90      std::vector<InputDeviceInfo> inputDevices;
91      { // acquire lock
92          std::scoped_lock _l(mLock);
93  
94          oldGeneration = mGeneration;
95          timeoutMillis = -1;
96  
。。。。。
107  
// 1)从eventhub 中获取驱动上报的事件 getEvents
108      size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
109  
110      { // acquire lock
111          std::scoped_lock _l(mLock);
112          mReaderIsAliveCondition.notify_all();
113  
114          if (count) {
// 2)处理上报的数据:processEventsLocked
115              processEventsLocked(mEventBuffer, count);
116          }
117  
。。。。
// 3)观察者队列去flush,处理全部的事件:flush
147      mQueuedListener->flush();
148  }

// 1)从eventhub 中获取驱动上报的事件 getEvents

1461  size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
1462      ALOG_ASSERT(bufferSize >= 1);
1463  
1464      std::scoped_lock _l(mLock);
1465  
1466      struct input_event readBuffer[bufferSize];
1467  
1468      RawEvent* event = buffer;
1469      size_t capacity = bufferSize;
1470      bool awoken = false;
1471      for (;;) {
1472          nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);

。。。。。。
1548          // Grab the next input event.
1549          bool deviceChanged = false;

// 设置 mPendingEventCount 值,则满足下列条件
1550          while (mPendingEventIndex < mPendingEventCount) {
1551              const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];

// 通过fd 获取到对应的 Device,创建对象为 std::make_unique<Device>(fd
1577              Device* device = getDeviceByFdLocked(eventItem.data.fd);

1605              if (eventItem.events & EPOLLIN) {
// 读取对应fd 的数据
1606                  int32_t readSize =
1607                          read(device->fd, readBuffer, sizeof(struct input_event) * capacity);

。。。。。
1621                  } else {
1622                      int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
1623  
1624                      size_t count = size_t(readSize) / sizeof(struct input_event);
1625                      for (size_t i = 0; i < count; i++) {
1626                          struct input_event& iev = readBuffer[i];
1627                          event->when = processEventTimestamp(iev);
1628                          event->readTime = systemTime(SYSTEM_TIME_MONOTONIC);
1629                          event->deviceId = deviceId;
// 将上报的type 和 code value 保存到 event  中,遍历所有然后退出
1630                          event->type = iev.type;
1631                          event->code = iev.code;
1632                          event->value = iev.value;
1633                          event += 1;
1634                          capacity -= 1;
1635                      }
1636                      if (capacity == 0) {
1637                          // The result buffer is full.  Reset the pending event index
1638                          // so we will try to read the device again on the next iteration.
1639                          mPendingEventIndex -= 1;
1640                          break;
1641                      }
1642                  }
。。。。。。
// 首先是epoll 监听底层的事件
1688          int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
1689  
1690          mLock.lock(); // reacquire lock after poll
。。。。。。。
1708          } else {
1709              // Some events occurred.
// 如果有事件的话 设置 mPendingEventCount 值
1710              mPendingEventCount = size_t(pollResult);
1711          }
1712      }
1713  
1714      // All done, return the number of events we read.
1715      return event - buffer;
1716  }

// 将上报的type 和 code value 保存到 event 中,遍历所有然后return退出,数据给到 processEventsLocked 处理。

// 2)处理上报的数据:processEventsLocked

  • processEventsLocked()函数中会遍历所有的事件,分别进行处理。其处理的事件类型分为四种:原始输入事件、设备加载事件、设备卸载事件及FINISHED_DEVICE_SCAN事件。

/frameworks/native/services/inputflinger/reader/InputReader.cpp

150  void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {

// 遍历处理所有的事件 rawEvent 
151      for (const RawEvent* rawEvent = rawEvents; count;) {
152          int32_t type = rawEvent->type;
153          size_t batchSize = 1;
154          if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
// 获取到设备的id
155              int32_t deviceId = rawEvent->deviceId;
156              while (batchSize < count) {
157                  if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT ||
158                      rawEvent[batchSize].deviceId != deviceId) {
159                      break;
160                  }
161                  batchSize += 1;
162              }
163  #if DEBUG_RAW_EVENTS
164              ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
165  #endif
// 处理事件 processEventsForDeviceLocked
166              processEventsForDeviceLocked(deviceId, rawEvent, batchSize);

================
296  void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,
297                                                 size_t count) {

// 通过hubid 找到对应的 InputDevice
298      auto deviceIt = mDevices.find(eventHubId);
299      if (deviceIt == mDevices.end()) {
300          ALOGW("Discarding event for unknown eventHubId %d.", eventHubId);
301          return;
302      }
303  
304      std::shared_ptr<InputDevice>& device = deviceIt->second;
305      if (device->isIgnored()) {
306          // ALOGD("Discarding event for ignored deviceId %d.", deviceId);
307          return;
308      }
309  

// 通过 InputDevice 去处理事件process
310      device->process(rawEvents, count);
311  }

// 通过 InputDevice 去处理事件process。

根据事件获得相应的设备类型,然后将事件交给相应的设备处理,给触摸设备相关的类去处理。

/frameworks/native/services/inputflinger/reader/InputDevice.cpp

375  void InputDevice::process(const RawEvent* rawEvents, size_t count) {

// 遍历所有的事件
381      for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
382  #if DEBUG_RAW_EVENTS
383          ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
384                rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value, rawEvent->when);
385  #endif
386  
387          if (mDropUntilNextSync) {
388              if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
389                  mDropUntilNextSync = false;
390  #if DEBUG_RAW_EVENTS
391                  ALOGD("Recovered from input event buffer overrun.");
392  #endif
393              } else {
394  #if DEBUG_RAW_EVENTS
395                  ALOGD("Dropped input event while waiting for next input sync.");
396  #endif
397              }
// 如果事件类型是 SYN_DROPPED,则drop 这个事件
398          } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
399              ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
400              mDropUntilNextSync = true;
401              reset(rawEvent->when);
402          } else {

// 遍历所有的mapper 去处理 rawevent
403              for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
404                  mapper.process(rawEvent);
405              });
406          }
407          --count;
408      }
409  }

========
// 遍历所有的mapper 去处理 rawevent
// 前面 addEventubDevice 的时候,将其MultiTouchInputMapper 增加到了mapper 中
195      inline void for_each_mapper_in_subdevice(int32_t eventHubDevice,
196                                               std::function<void(InputMapper&)> f) {
197          auto deviceIt = mDevices.find(eventHubDevice);
198          if (deviceIt != mDevices.end()) {
199              auto& devicePair = deviceIt->second;
200              auto& mappers = devicePair.second;
201              for (auto& mapperPtr : mappers) {
202                  f(*mapperPtr);
203              }
204          }
205      }

调用 MultiTouchInputMapper 的process 方法

/frameworks/native/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp

238  void MultiTouchInputMapper::process(const RawEvent* rawEvent) {

// 2-1)TouchInputMapper 先进行处理 process
239      TouchInputMapper::process(rawEvent);
240  

// 2-2)MultiTouchMotionAccumulator 处理rawEvent:process
241      mMultiTouchMotionAccumulator.process(rawEvent);
242  }

其实是先处理process,然后再去

// 2-2)MultiTouchMotionAccumulator 处理rawEvent:process

通过 MultiTouchMotionAccumulator.process处理了

85  void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
86      if (rawEvent->type == EV_ABS) {
87          bool newSlot = false;
。。。。。。。
105          } else {

// mCurrentSlot 为当前的手指
106              Slot* slot = &mSlots[mCurrentSlot];
107              // If mUsingSlotsProtocol is true, it means the raw pointer has axis info of
108              // ABS_MT_TRACKING_ID and ABS_MT_SLOT, so driver should send a valid trackingId while
109              // updating the slot.
110              if (!mUsingSlotsProtocol) {
// 设置为true
111                  slot->mInUse = true;
112              }
113  
114              switch (rawEvent->code) {
// 设置对应的xy 轴值
115                  case ABS_MT_POSITION_X:
116                      slot->mAbsMTPositionX = rawEvent->value;
117                      warnIfNotInUse(*rawEvent, *slot);
118                      break;
119                  case ABS_MT_POSITION_Y:
120                      slot->mAbsMTPositionY = rawEvent->value;
121                      warnIfNotInUse(*rawEvent, *slot);
122                      break;
123                  case ABS_MT_TOUCH_MAJOR:
124                      slot->mAbsMTTouchMajor = rawEvent->value;
125                      break;
126                  case ABS_MT_TOUCH_MINOR:
127                      slot->mAbsMTTouchMinor = rawEvent->value;
128                      slot->mHaveAbsMTTouchMinor = true;
129                      break;
130                  case ABS_MT_WIDTH_MAJOR:
131                      slot->mAbsMTWidthMajor = rawEvent->value;
132                      break;
133                  case ABS_MT_WIDTH_MINOR:
134                      slot->mAbsMTWidthMinor = rawEvent->value;
135                      slot->mHaveAbsMTWidthMinor = true;
136                      break;
137                  case ABS_MT_ORIENTATION:
138                      slot->mAbsMTOrientation = rawEvent->value;
139                      break;

// trackid 为手指数,表示第几个手指
140                  case ABS_MT_TRACKING_ID:
141                      if (mUsingSlotsProtocol && rawEvent->value < 0) {
142                          // The slot is no longer in use but it retains its previous contents,
143                          // which may be reused for subsequent touches.
144                          slot->mInUse = false;
145                      } else {
146                          slot->mInUse = true;
// 设置 mAbsMTTrackingId 
147                          slot->mAbsMTTrackingId = rawEvent->value;
148                      }
149                      break;
150                  case ABS_MT_PRESSURE:
151                      slot->mAbsMTPressure = rawEvent->value;
152                      break;
153                  case ABS_MT_DISTANCE:
154                      slot->mAbsMTDistance = rawEvent->value;
155                      break;
156                  case ABS_MT_TOOL_TYPE:
157                      slot->mAbsMTToolType = rawEvent->value;
158                      slot->mHaveAbsMTToolType = true;
159                      break;
160              }
161          }

// 如果类型是结束的话,则设置 mCurrentSlot 增加1
162      } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
163          // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
164          mCurrentSlot += 1;
165      }
166  }

// 2-1)TouchInputMapper 先进行处理 process

处理是上一次的结果,通过 MultiTouchMotionAccumulator.process处理了

/frameworks/native/services/inputflinger/reader/mapper/TouchInputMapper.cpp

1425  void TouchInputMapper::process(const RawEvent* rawEvent) {
1426      mCursorButtonAccumulator.process(rawEvent);
1427      mCursorScrollAccumulator.process(rawEvent);
1428      mTouchButtonAccumulator.process(rawEvent);
1429  

// 如果事件是结束了的话,则执行sync
1430      if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
1431          sync(rawEvent->when, rawEvent->readTime);
1432      }
1433  }

=========
1435  void TouchInputMapper::sync(nsecs_t when, nsecs_t readTime) {
1436      // Push a new state.
1437      mRawStatesPending.emplace_back();
1438  
1439      RawState& next = mRawStatesPending.back();
1440      next.clear();
1441      next.when = when;
1442      next.readTime = readTime;
1443  
1444      // Sync button state.
1445      next.buttonState =
1446              mTouchButtonAccumulator.getButtonState() | mCursorButtonAccumulator.getButtonState();
1447  
1448      // Sync scroll
1449      next.rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
1450      next.rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
1451      mCursorScrollAccumulator.finishSync();
1452  

// 2-1-1)同步触摸事件 syncTouch
1454      syncTouch(when, &next);
1455  
1456      // The last RawState is the actually second to last, since we just added a new state
1457      const RawState& last =
1458              mRawStatesPending.size() == 1 ? mCurrentRawState : mRawStatesPending.rbegin()[1];
1459  
1460      // Assign pointer ids.
1461      if (!mHavePointerIds) {
1462          assignPointerIds(last, next);
1463      }
1464  

// 打开开关会打印下列的log,对应的 pointerCount 手指数量
1465  #if DEBUG_RAW_EVENTS
1466      ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
1467            "hovering ids 0x%08x -> 0x%08x, canceled ids 0x%08x",
1468            last.rawPointerData.pointerCount, next.rawPointerData.pointerCount,
1469            last.rawPointerData.touchingIdBits.value, next.rawPointerData.touchingIdBits.value,
1470            last.rawPointerData.hoveringIdBits.value, next.rawPointerData.hoveringIdBits.value,
1471            next.rawPointerData.canceledIdBits.value);
1472  #endif
1473  
1474      if (!next.rawPointerData.touchingIdBits.isEmpty() &&
1475          !next.rawPointerData.hoveringIdBits.isEmpty() &&
1476          last.rawPointerData.hoveringIdBits != next.rawPointerData.hoveringIdBits) {
1477          ALOGI("Multi-touch contains some hovering ids 0x%08x",
1478                next.rawPointerData.hoveringIdBits.value);
1479      }
1480  

// 2-1-2)处理触摸事件:processRawTouches
1481      processRawTouches(false /*timeout*/);
1482  }

input设备类型有很多种,以上只是触摸设备的inputmapper:MultiTouchInputMapper,还有下列几种

  • 键盘类设备:KeyboardInputMapper
  • 触摸屏设备:MultiTouchInputMapper或SingleTouchInputMapper
  • 鼠标类设备:CursorInputMapper

// 2-1-1)同步触摸事件 syncTouch,调用的是子类的方法

/frameworks/native/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp

最大的手指的数量为 16 个

178  #define MAX_POINTERS 16

258  void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
/// 获取的数量值为配置的值
259      size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
260      size_t outCount = 0;
261      BitSet32 newPointerIdBits;
262      mHavePointerIds = true;
263  

// 获取到对应的slot
264      for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
265          const MultiTouchMotionAccumulator::Slot* inSlot =
266                  mMultiTouchMotionAccumulator.getSlot(inIndex);
267          if (!inSlot->isInUse()) {
268              continue;
269          }

。。。。
// 如果超过最大18个手指,则break
283          if (outCount >= MAX_POINTERS) {
284  #if DEBUG_POINTERS
285              ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
286                    "ignoring the rest.",
287                    getDeviceName().c_str(), MAX_POINTERS);
288  #endif
289              break; // too many fingers!
290          }
291  

// 获取到 RawPointerData::Pointer,设置对应的手指的参数
292          RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
// 设置xy 轴的值
293          outPointer.x = inSlot->getX();
294          outPointer.y = inSlot->getY();
295          outPointer.pressure = inSlot->getPressure();
296          outPointer.touchMajor = inSlot->getTouchMajor();
297          outPointer.touchMinor = inSlot->getTouchMinor();
298          outPointer.toolMajor = inSlot->getToolMajor();
299          outPointer.toolMinor = inSlot->getToolMinor();
300          outPointer.orientation = inSlot->getOrientation();
301          outPointer.distance = inSlot->getDistance();
302          outPointer.tiltX = 0;
303          outPointer.tiltY = 0;
304  
305          outPointer.toolType = inSlot->getToolType();
306          if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
307              outPointer.toolType = mTouchButtonAccumulator.getToolType();
308              if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
309                  outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
310              }
311          }

。。。。
318          // Assign pointer id using tracking id if available.
319          if (mHavePointerIds) {
320              int32_t trackingId = inSlot->getTrackingId();
321              int32_t id = -1;
322              if (trackingId >= 0) {
323                  for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty();) {
324                      uint32_t n = idBits.clearFirstMarkedBit();
325                      if (mPointerTrackingIdMap[n] == trackingId) {
326                          id = n;
327                      }
328                  }
329  
330                  if (id < 0 && !mPointerIdBits.isFull()) {
331                      id = mPointerIdBits.markFirstUnmarkedBit();
332                      mPointerTrackingIdMap[id] = trackingId;
333                  }
334              }
335              if (id < 0) {
336                  mHavePointerIds = false;
337                  outState->rawPointerData.clearIdBits();
338                  newPointerIdBits.clear();
339              } else {
340                  outPointer.id = id;
341                  outState->rawPointerData.idToIndex[id] = outCount;
342                  outState->rawPointerData.markIdBit(id, isHovering);
343                  newPointerIdBits.markBit(id);
344              }
345          }
346          outCount += 1;
347      }
348  
349      outState->rawPointerData.pointerCount = outCount;
350      mPointerIdBits = newPointerIdBits;
351  
352      mMultiTouchMotionAccumulator.finishSync();
353  }

// 2-1-2)处理触摸事件:processRawTouches

//将RawState的数据复制到 mCurrentRawState

1484  void TouchInputMapper::processRawTouches(bool timeout) {
1485      if (mDeviceMode == DeviceMode::DISABLED) {
1486          // Drop all input if the device is disabled.
1487          cancelTouch(mCurrentRawState.when, mCurrentRawState.readTime);
1488          mCurrentCookedState.clear();
1489          updateTouchSpots();
1490          return;
1491      }

// 遍历所有的 RawState
1497      const size_t N = mRawStatesPending.size();
1498      size_t count;
1499      for (count = 0; count < N; count++) {
1500          const RawState& next = mRawStatesPending[count];

1504          if (assignExternalStylusId(next, timeout)) {
1505              break;
1506          }
1507  
1508          // All ready to go.
1509          clearStylusDataPendingFlags();
//将RawState的数据复制到 mCurrentRawState 
1510          mCurrentRawState.copyFrom(next);
1511          if (mCurrentRawState.when < mLastRawState.when) {
1512              mCurrentRawState.when = mLastRawState.when;
1513              mCurrentRawState.readTime = mLastRawState.readTime;
1514          }

// 处理这个数据并分发:cookAndDispatch
1515          cookAndDispatch(mCurrentRawState.when, mCurrentRawState.readTime);
1516      }

// 处理这个数据并分发:cookAndDispatch

1538  void TouchInputMapper::cookAndDispatch(nsecs_t when, nsecs_t readTime) {
1539      // Always start with a clean state.
1540      mCurrentCookedState.clear();
1541  
1542      // Apply stylus buttons to current raw state.
1543      applyExternalStylusButtonState(when);
1544  
1545      // Handle policy on initial down or hover events.
1546      bool initialDown = mLastRawState.rawPointerData.pointerCount == 0 &&
1547              mCurrentRawState.rawPointerData.pointerCount != 0;
1548  
1549      uint32_t policyFlags = 0;
1550      bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
1551      if (initialDown || buttonsPressed) {
1552          // If this is a touch screen, hide the pointer on an initial down.
1553          if (mDeviceMode == DeviceMode::DIRECT) {
1554              getContext()->fadePointer();
1555          }
1556  
1557          if (mParameters.wake) {
1558              policyFlags |= POLICY_FLAG_WAKE;
1559          }
1560      }
1564      if (consumeRawTouches(when, readTime, policyFlags)) {
1565          mCurrentRawState.rawPointerData.clear();
1566      }

// 处理pointer 数据:cookPointerData
1571      cookPointerData();

// 设备类型是 DIRECT        
1582      if (mDeviceMode == DeviceMode::POINTER) {
。。。。
1622      } else {
1623          updateTouchSpots();
1624  
1625          if (!mCurrentMotionAborted) {
1626              dispatchButtonRelease(when, readTime, policyFlags);
1627              dispatchHoverExit(when, readTime, policyFlags);
// 分发tounch 事件 dispatchTouches
1628              dispatchTouches(when, readTime, policyFlags);
1629              dispatchHoverEnterAndMove(when, readTime, policyFlags);
1630              dispatchButtonPress(when, readTime, policyFlags);
1631          }

// 处理pointer 数据:cookPointerData

2075  void TouchInputMapper::cookPointerData() {
// 设置按下手指的数量
2076      uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
2077  
2078      mCurrentCookedState.cookedPointerData.clear();
2079      mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
2080      mCurrentCookedState.cookedPointerData.hoveringIdBits =
2081              mCurrentRawState.rawPointerData.hoveringIdBits;
2082      mCurrentCookedState.cookedPointerData.touchingIdBits =
2083              mCurrentRawState.rawPointerData.touchingIdBits;
2084      mCurrentCookedState.cookedPointerData.canceledIdBits =
2085              mCurrentRawState.rawPointerData.canceledIdBits;
。。。。
2095      for (uint32_t i = 0; i < currentPointerCount; i++) {
2096          const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
2097  
2098          // Size
2099          float touchMajor, touchMinor, toolMajor, toolMinor, size;
2100          switch (mCalibration.sizeCalibration) {
2101              case Calibration::SizeCalibration::GEOMETRIC:
2102              case Calibration::SizeCalibration::DIAMETER:
2103              case Calibration::SizeCalibration::BOX:
2104              case Calibration::SizeCalibration::AREA:
。。。。
// 设置对应的touchMajor
2112                  } else if (mRawPointerAxes.touchMajor.valid) {
2113                      toolMajor = touchMajor = in.touchMajor;
2114                      toolMinor = touchMinor =
2115                              mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
2116                      size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor)
2117                                                              : in.touchMajor;
.。。。。。
// 进行仿射变换 
2250          float xTransformed = in.x, yTransformed = in.y;
2251          mAffineTransform.applyTo(xTransformed, yTransformed);
2252          rotateAndScale(xTransformed, yTransformed);
。。。。。。

// 将其数据保存到 mCurrentCookedState.cookedPointerData.pointerCoords
2302          // Write output coords.
2303          PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
2304          out.clear();
2305          out.setAxisValue(AMOTION_EVENT_AXIS_X, xTransformed);
2306          out.setAxisValue(AMOTION_EVENT_AXIS_Y, yTransformed);
2307          out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
2308          out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
2309          out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
2310          out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
2311          out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
2312          out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
2313          out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);

// 分发tounch 事件 dispatchTouches

1904  void TouchInputMapper::dispatchTouches(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) {
1905      BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
1906      BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
1907      int32_t metaState = getContext()->getGlobalMetaState();
1908      int32_t buttonState = mCurrentCookedState.buttonState;
1909  
1910      if (currentIdBits == lastIdBits) {
。。。。。
1921      } else {

// 判断是up,down还是move 事件
1924          BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
1925          BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
1926          BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
1927          BitSet32 dispatchedIdBits(lastIdBits.value);
1928  
1929          // Update last coordinates of pointers that have moved so that we observe the new
1930          // pointer positions at the same time as other pointers that have just gone up.
1931          bool moveNeeded =
1932                  updateMovedPointers(mCurrentCookedState.cookedPointerData.pointerProperties,
1933                                      mCurrentCookedState.cookedPointerData.pointerCoords,
1934                                      mCurrentCookedState.cookedPointerData.idToIndex,
1935                                      mLastCookedState.cookedPointerData.pointerProperties,
1936                                      mLastCookedState.cookedPointerData.pointerCoords,
1937                                      mLastCookedState.cookedPointerData.idToIndex, moveIdBits);
1938          if (buttonState != mLastCookedState.buttonState) {
1939              moveNeeded = true;
1940          }
1941  

// 遍历所有的up 事件
1943          while (!upIdBits.isEmpty()) {
// 对应的up 的按钮:upId 
1944              uint32_t upId = upIdBits.clearFirstMarkedBit();
1945              bool isCanceled = mCurrentCookedState.cookedPointerData.canceledIdBits.hasBit(upId);
1946              if (isCanceled) {
1947                  ALOGI("Canceling pointer %d for the palm event was detected.", upId);
1948              }

// up 的事件为 AMOTION_EVENT_ACTION_POINTER_UP,事件保存再 cookedPointerData.pointerCoords:走dispatchMotion 方法 
1949              dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_UP, 0,
1950                             isCanceled ? AMOTION_EVENT_FLAG_CANCELED : 0, metaState, buttonState, 0,
1951                             mLastCookedState.cookedPointerData.pointerProperties,
1952                             mLastCookedState.cookedPointerData.pointerCoords,
1953                             mLastCookedState.cookedPointerData.idToIndex, dispatchedIdBits, upId,
1954                             mOrientedXPrecision, mOrientedYPrecision, mDownTime);
1955              dispatchedIdBits.clearBit(upId);
1956              mCurrentCookedState.cookedPointerData.canceledIdBits.clearBit(upId);
1957          }

// up 的事件为 AMOTION_EVENT_ACTION_POINTER_UP,事件保存再 cookedPointerData.pointerCoords:走dispatchMotion 方法

3601  void TouchInputMapper::dispatchMotion(nsecs_t when, nsecs_t readTime, uint32_t policyFlags,
3602                                        uint32_t source, int32_t action, int32_t actionButton,
3603                                        int32_t flags, int32_t metaState, int32_t buttonState,
3604                                        int32_t edgeFlags, const PointerProperties* properties,
3605                                        const PointerCoords* coords, const uint32_t* idToIndex,
3606                                        BitSet32 idBits, int32_t changedId, float xPrecision,
3607                                        float yPrecision, nsecs_t downTime) {
3608      PointerCoords pointerCoords[MAX_POINTERS];
3609      PointerProperties pointerProperties[MAX_POINTERS];
3610      uint32_t pointerCount = 0;
3611      while (!idBits.isEmpty()) {
3612          uint32_t id = idBits.clearFirstMarkedBit();
3613          uint32_t index = idToIndex[id];
3614          pointerProperties[pointerCount].copyFrom(properties[index]);

// 将数据保存到pointerCoords 中
3615          pointerCoords[pointerCount].copyFrom(coords[index]);
3616  

// changedId 为up 的事件
3617          if (changedId >= 0 && id == uint32_t(changedId)) {
3618              action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
3619          }
3620  
3621          pointerCount += 1;
3622      }
3623  
3624      ALOG_ASSERT(pointerCount != 0);
3625  

// 如果是单指的话,则将up事件更换为 AMOTION_EVENT_ACTION_UP
3626      if (changedId >= 0 && pointerCount == 1) {
3627          // Replace initial down and final up action.
3628          // We can compare the action without masking off the changed pointer index
3629          // because we know the index is 0.
3630          if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
3631              action = AMOTION_EVENT_ACTION_DOWN;
3632          } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
3633              if ((flags & AMOTION_EVENT_FLAG_CANCELED) != 0) {
3634                  action = AMOTION_EVENT_ACTION_CANCEL;
3635              } else {
3636                  action = AMOTION_EVENT_ACTION_UP;
3637              }
3638          } else {
3639              // Can't happen.
3640              ALOG_ASSERT(false);
3641          }
3642      }
。。。。。。。
3650      const int32_t displayId = getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE);
3651      const int32_t deviceId = getDeviceId();
3652      std::vector<TouchVideoFrame> frames = getDeviceContext().getVideoFrames();
3653      std::for_each(frames.begin(), frames.end(),
3654                    [this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); });

// 创建了 NotifyMotionArgs 对象,pointerCoords 为对应保存的数据
3655      NotifyMotionArgs args(getContext()->getNextId(), when, readTime, deviceId, source, displayId,
3656                            policyFlags, action, actionButton, flags, metaState, buttonState,
3657                            MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties,
3658                            pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
3659                            downTime, std::move(frames));
3660      getListener()->notifyMotion(&args);
3661  }

NotifyMotionArgs 重点的参数:

deviceId:设备id

action:up还是什么其他事件 AMOTION_EVENT_ACTION_UP

actionButton: 为0

flags:0

pointerCount:手指的数量

pointerCoords:保存的数据,表示是 xy 坐标,压力值、major等值

xPrecision, yPrecision:与屏幕方向有关

xCursorPosition, yCursorPosition:都是无效的

notifymotion 通知到 InputDispatcher

/frameworks/native/services/inputflinger/reader/mapper/TouchInputMapper.cpp

3601  void TouchInputMapper::dispatchMotion(nsecs_t when, nsecs_t readTime, uint32_t policyFlags,
3602                                        uint32_t source, int32_t action, int32_t actionButton,
3603                                        int32_t flags, int32_t metaState, int32_t buttonState,
3604                                        int32_t edgeFlags, const PointerProperties* properties,
3605                                        const PointerCoords* coords, const uint32_t* idToIndex,
3606                                        BitSet32 idBits, int32_t changedId, float xPrecision,
3607                                        float yPrecision, nsecs_t downTime) {
3608      PointerCoords pointerCoords[MAX_POINTERS];
3609      PointerProperties pointerProperties[MAX_POINTERS];
3610      uint32_t pointerCount = 0;
3611      while (!idBits.isEmpty()) {
3612          uint32_t id = idBits.clearFirstMarkedBit();
3613          uint32_t index = idToIndex[id];
3614          pointerProperties[pointerCount].copyFrom(properties[index]);
3615          pointerCoords[pointerCount].copyFrom(coords[index]);
3616  
3617          if (changedId >= 0 && id == uint32_t(changedId)) {
3618              action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
3619          }
3620  
3621          pointerCount += 1;
3622      }
3623  
3624      ALOG_ASSERT(pointerCount != 0);
3625  

// 如果是单指的话,则会将AMOTION_EVENT_ACTION_POINTER_UP设置为 AMOTION_EVENT_ACTION_UP
3626      if (changedId >= 0 && pointerCount == 1) {
3627          // Replace initial down and final up action.
3628          // We can compare the action without masking off the changed pointer index
3629          // because we know the index is 0.
3630          if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
3631              action = AMOTION_EVENT_ACTION_DOWN;
3632          } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
3633              if ((flags & AMOTION_EVENT_FLAG_CANCELED) != 0) {
3634                  action = AMOTION_EVENT_ACTION_CANCEL;
3635              } else {
3636                  action = AMOTION_EVENT_ACTION_UP;
3637              }
3638          } else {
3639              // Can't happen.
3640              ALOG_ASSERT(false);
3641          }
3642      }
3643      float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
3644      float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
3645      if (mDeviceMode == DeviceMode::POINTER) {
3646          auto [x, y] = getMouseCursorPosition();
3647          xCursorPosition = x;
3648          yCursorPosition = y;
3649      }
3650      const int32_t displayId = getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE);
3651      const int32_t deviceId = getDeviceId();
3652      std::vector<TouchVideoFrame> frames = getDeviceContext().getVideoFrames();
3653      std::for_each(frames.begin(), frames.end(),
3654                    [this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); });

// 将所有的参数封装为 NotifyMotionArgs 
3655      NotifyMotionArgs args(getContext()->getNextId(), when, readTime, deviceId, source, displayId,
3656                            policyFlags, action, actionButton, flags, metaState, buttonState,
3657                            MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties,
3658                            pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
3659                            downTime, std::move(frames));

// getListener 去通知到观察者
3660      getListener()->notifyMotion(&args);
3661  }

getListener 的实现为:

/frameworks/native/services/inputflinger/reader/mapper/InputMapper.h

TouchInputMapper 类继承了 InputMapper

// 这里获取到context,通过 mDeviceContext.getContext()
49      inline InputReaderContext* getContext() { return mDeviceContext.getContext(); }

// 通过ceontext 获取到 Listener
51      inline InputListenerInterface* getListener() { return getContext()->getListener(); }

mDeviceContext 是在初始化 传入的

/frameworks/native/services/inputflinger/reader/InputDevice.cpp

143  void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
144      if (mDevices.find(eventHubId) != mDevices.end()) {
145          return;
146      }
147      std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));

。。。。
204      // Touchscreens and touchpad devices.
205      if (classes.test(InputDeviceClass::TOUCH_MT)) {

// contextPtr 是 InputDeviceContext 对象
206          mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));

所以 mDeviceContext 是 InputDeviceContext,再调用其 getContext 方法

/frameworks/native/services/inputflinger/reader/include/InputDevice.h

239  class InputDeviceContext {
240  public:
241      InputDeviceContext(InputDevice& device, int32_t eventHubId);
242      ~InputDeviceContext();
243  
244      inline InputReaderContext* getContext() { return mContext; }

========
600  InputDeviceContext::InputDeviceContext(InputDevice& device, int32_t eventHubId)
601        : mDevice(device),

// 为构造函数中传入的,即通过 InputDevice.getContext 获取
602          mContext(device.getContext()),
603          mEventHub(device.getContext()->getEventHub()),
604          mId(eventHubId),

// 为构造函数中传入的,即通过 InputDevice.getContext 获取

也是再 InputDevice 中传入的

44  class InputDevice {
45  public:
46      InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
47                  const InputDeviceIdentifier& identifier);
48      ~InputDevice();
49  
50      inline InputReaderContext* getContext() { return mContext; }

mContext 为内部的类为 ContextImpl

/frameworks/native/services/inputflinger/reader/include/InputReader.h

124      class ContextImpl : public InputReaderContext {
125          InputReader* mReader;
126          IdGenerator mIdGenerator;
127  
128      public:
129          explicit ContextImpl(InputReader* reader);
130          // lock is already held by the input loop
131          void updateGlobalMetaState() NO_THREAD_SAFETY_ANALYSIS override;
132          int32_t getGlobalMetaState() NO_THREAD_SAFETY_ANALYSIS override;
133          void disableVirtualKeysUntil(nsecs_t time) REQUIRES(mReader->mLock) override;
134          bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode)
135                  REQUIRES(mReader->mLock) override;
136          void fadePointer() REQUIRES(mReader->mLock) override;
137          std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId)
138                  REQUIRES(mReader->mLock) override;
139          void requestTimeoutAtTime(nsecs_t when) REQUIRES(mReader->mLock) override;
140          int32_t bumpGeneration() NO_THREAD_SAFETY_ANALYSIS override;
141          void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices)
142                  REQUIRES(mReader->mLock) override;
143          void dispatchExternalStylusState(const StylusState& outState)
144                  REQUIRES(mReader->mLock) override;
145          InputReaderPolicyInterface* getPolicy() REQUIRES(mReader->mLock) override;
146          InputListenerInterface* getListener() REQUIRES(mReader->mLock) override;
147          EventHubInterface* getEventHub() REQUIRES(mReader->mLock) override;
148          int32_t getNextId() NO_THREAD_SAFETY_ANALYSIS override;
149          void updateLedMetaState(int32_t metaState) REQUIRES(mReader->mLock) override;
150          int32_t getLedMetaState() REQUIRES(mReader->mLock) REQUIRES(mLock) override;
151      } mContext;

综上:

InputReaderContext* getContext() 返回的对象是 InputReader 的 ContextImpl

接着调用其 listener 的方法:

/frameworks/native/services/inputflinger/reader/InputReader.cpp

948  InputListenerInterface* InputReader::ContextImpl::getListener() {
// 获取到的是 对象
949      return mReader->mQueuedListener.get();
950  }

======
43  InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
44                           const sp<InputReaderPolicyInterface>& policy,
// listener 传入的参数是 InputDispatcher
45                           const sp<InputListenerInterface>& listener)
46        : mContext(this),
47          mEventHub(eventHub),
48          mPolicy(policy),
49          mGlobalMetaState(0),
50          mLedMetaState(AMETA_NUM_LOCK_ON),
51          mGeneration(1),
52          mNextInputDeviceId(END_RESERVED_ID),
53          mDisableVirtualKeysTimeout(LLONG_MIN),
54          mNextTimeout(LLONG_MAX),
55          mConfigurationChangesToRefresh(0) {
56      mQueuedListener = new QueuedInputListener(listener);

所以是调用到 QueuedInputListener 的方法 notifyMotion

/frameworks/native/services/inputflinger/InputListener.cpp

315  QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
316          mInnerListener(innerListener) {
317  }

337  void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
338      traceEvent(__func__, args->id);

// 创建 NotifyMotionArgs 对象包装 args,将其保存到参数队列中
339      mArgsQueue.push_back(new NotifyMotionArgs(*args));
340  }

========
// 最后需要调用flush,去统一派发
367  void QueuedInputListener::flush() {
368      size_t count = mArgsQueue.size();
369      for (size_t i = 0; i < count; i++) {
370          NotifyArgs* args = mArgsQueue[i];
371          args->notify(mInnerListener);
372          delete args;
373      }
374      mArgsQueue.clear();
375  }

=======
// 然后调用观察者 InputDispatcher 去通知触摸事件 notifyMotion
191  void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {
192      listener->notifyMotion(this);
193  }

// 3)观察者队列去flush,处理全部的事件:flush

调用观察者 InputDispatcher 去通知触摸事件 notifyMotion

/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp

3817  void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
3818  #if DEBUG_INBOUND_EVENT_DETAILS

// 会打印对应的log
3819      ALOGD("notifyMotion - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=0x%x, "
3820            "displayId=%" PRId32 ", policyFlags=0x%x, "
3821            "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, "
3822            "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, xCursorPosition=%f, "
3823            "yCursorPosition=%f, downTime=%" PRId64,
3824            args->id, args->eventTime, args->deviceId, args->source, args->displayId,
3825            args->policyFlags, args->action, args->actionButton, args->flags, args->metaState,
3826            args->buttonState, args->edgeFlags, args->xPrecision, args->yPrecision,
3827            args->xCursorPosition, args->yCursorPosition, args->downTime);
3828      for (uint32_t i = 0; i < args->pointerCount; i++) {
3829          ALOGD("  Pointer %d: id=%d, toolType=%d, "
3830                "x=%f, y=%f, pressure=%f, size=%f, "
3831                "touchMajor=%f, touchMinor=%f, toolMajor=%f, toolMinor=%f, "
3832                "orientation=%f",
3833                i, args->pointerProperties[i].id, args->pointerProperties[i].toolType,
3834                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_X),
3835                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_Y),
3836                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE),
3837                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_SIZE),
3838                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR),
3839                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR),
3840                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR),
3841                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR),
3842                args->pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION));
3843      }

。。。。。
3885          // Just enqueue a new motion event.

// 将args 封装为 MotionEntry 对象
3886          std::unique_ptr<MotionEntry> newEntry =
3887                  std::make_unique<MotionEntry>(args->id, args->eventTime, args->deviceId,
3888                                                args->source, args->displayId, policyFlags,
3889                                                args->action, args->actionButton, args->flags,
3890                                                args->metaState, args->buttonState,
3891                                                args->classification, args->edgeFlags,
3892                                                args->xPrecision, args->yPrecision,
3893                                                args->xCursorPosition, args->yCursorPosition,
3894                                                args->downTime, args->pointerCount,
3895                                                args->pointerProperties, args->pointerCoords, 0, 0);
3896  

// 将其假如到处理的队列,然后唤醒 inputdispatcher 线程
3897          needWake = enqueueInboundEventLocked(std::move(newEntry));
3898          mLock.unlock();
3899      } // release lock
3900  
3901      if (needWake) {
3902          mLooper->wake();
3903      }
3904  }
相关推荐
了一li2 小时前
Qt中的QProcess与Boost.Interprocess:实现多进程编程
服务器·数据库·qt
码农君莫笑2 小时前
信管通低代码信息管理系统应用平台
linux·数据库·windows·低代码·c#·.net·visual studio
别致的影分身2 小时前
使用C语言连接MySQL
数据库·mysql
京东零售技术4 小时前
“慢”增长时代的企业数据体系建设:超越数据中台
数据库
sdaxue.com4 小时前
帝国CMS:如何去掉帝国CMS登录界面的认证码登录
数据库·github·网站·帝国cms·认证码
o(╥﹏╥)5 小时前
linux(ubuntu )卡死怎么强制重启
linux·数据库·ubuntu·系统安全
阿里嘎多学长5 小时前
docker怎么部署高斯数据库
运维·数据库·docker·容器
Yuan_o_5 小时前
Linux 基本使用和程序部署
java·linux·运维·服务器·数据库·后端
Sunyanhui15 小时前
牛客网 SQL36查找后排序
数据库·sql·mysql
老王笔记6 小时前
MHA binlog server
数据库·mysql