Android11 InputReader分析

InputReader线程主要负责读取输入数据,并把数据交给InputDispatcher线程。本文以多指触摸屏为例,梳理一下InputReader的流程。
InputReader线程主要完成以下工作:

  • 处理已有的输入设备
  • 处理新增或者移除的输入设备
  • 对输入设备产生的输入数据进行处理

InputReader线程启动后,调用loopOnce方法

//frameworks\native\services\inputflinger\reader\InputReader.cpp
void InputReader::loopOnce() {
    //省略

    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);//1

    { // acquire lock
        AutoMutex _l(mLock);
        mReaderIsAliveCondition.broadcast();

        if (count) {
            processEventsLocked(mEventBuffer, count);//2
        }

   		//省略
    } // release lock

    // Send out a message that the describes the changed input devices.
    if (inputDevicesChanged) {
        mPolicy->notifyInputDevicesChanged(inputDevices);
    }
    //省略
	mQueuedListener->flush();//3

注释1处获取数据,注释2处理数据,注释3处将数据交给InputDispatcher线程。这个loopOnce方法会被循环调用。接下来分开分析InputReader线程需要完成的工作。

处理已有的输入设备

首先是调用EventHub的getEvents方法

//frameworks\native\services\inputflinger\reader\EventHub.cpp
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {

	RawEvent* event = buffer;
	
	for (;;) {
		//省略
		if (mNeedToScanDevices) {//默认为true
            mNeedToScanDevices = false;
            scanDevicesLocked();//1
            mNeedToSendFinishedDeviceScan = true;
        }
        while (mOpeningDevices != nullptr) {//2
            Device* device = mOpeningDevices;
            ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
            mOpeningDevices = device->next;
            event->when = now;
            event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
            event->type = DEVICE_ADDED;
            event += 1;
            mNeedToSendFinishedDeviceScan = true;
            if (--capacity == 0) {
                break;
            }
        }

        if (mNeedToSendFinishedDeviceScan) {//3
            mNeedToSendFinishedDeviceScan = false;
            event->when = now;
            event->type = FINISHED_DEVICE_SCAN;
            event += 1;
            if (--capacity == 0) {
                break;
            }
        }
		
		//省略

		if (event != buffer || awoken) {//4
            break;
        }
        //省略
	}

}

注释1处,调用scanDevicesLocked来扫描已存在的输入设备。注释2处对已经打开的输入设备,构造event,event的type为DEVICE_ADDED表示增加设备。注释3处表示扫描完成,增加一个type为FINISHED_DEVICE_SCAN的event。注释4处,此时event指向的地址不等于buffer,跳出循环,会回到InputReader的loopOnce方法,继续往下执行,调用processEventsLocked处理这些event。

先来看一下scanDevicesLocked方法

//frameworks\native\services\inputflinger\reader\EventHub.cpp
void EventHub::scanDevicesLocked() {
    status_t result = scanDirLocked(DEVICE_PATH);
  	//省略 
}

继续调用scanDirLocked处理,DEVICE_PATH为“dev/input”

//frameworks\native\services\inputflinger\reader\EventHub.cpp
status_t EventHub::scanDirLocked(const char* dirname) {
    char devname[PATH_MAX];
    char* filename;
    DIR* dir;
    struct dirent* de;
    dir = opendir(dirname);//1
    if (dir == nullptr) return -1;
    strcpy(devname, dirname);
    filename = devname + strlen(devname);
    *filename++ = '/';
    while ((de = readdir(dir))) {
        if (de->d_name[0] == '.' &&
            (de->d_name[1] == '\0' || (de->d_name[1] == '.' && de->d_name[2] == '\0')))
            continue;
        strcpy(filename, de->d_name);
        openDeviceLocked(devname);//2
    }
    closedir(dir);
    return 0;
}

注释1处打开dev/input这个目录,dev/input这个目录下代表的是一个个的输入设备,注释2处对目录下的每个设备,调用openDeviceLocked处理

//frameworks\native\services\inputflinger\reader\EventHub.cpp
status_t EventHub::openDeviceLocked(const char* devicePath) {

	int fd = open(devicePath, O_RDWR | O_CLOEXEC | O_NONBLOCK);//打开设备,得到fd
	
	//省略
	int32_t deviceId = mNextDeviceId++;
    Device* device = new Device(fd, deviceId, devicePath, identifier);//新建Device对象
    //省略
    if (test_bit(ABS_MT_POSITION_X, device->absBitmask) &&
        test_bit(ABS_MT_POSITION_Y, device->absBitmask)) {
        // Some joysticks such as the PS3 controller report axes that conflict
        // with the ABS_MT range.  Try to confirm that the device really is
        // a touch screen.
        if (test_bit(BTN_TOUCH, device->keyBitmask) || !haveGamepadButtons) {
            device->classes |= INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_TOUCH_MT;//对于多指触摸
        }
	
	//省略
	if (registerDeviceForEpollLocked(device) != OK) {//1
        delete device;
        return -1;
    }

	addDeviceLocked(device);//2
}

新建Device对象后,对于多指触摸,设置其classes 为INPUT_DEVICE_CLASS_TOUCH 和INPUT_DEVICE_CLASS_TOUCH_MT。注释1处将打开的设备添加进epoll中监听。注释2处将创建的Device对象添加到mDevices集合中并设置mOpeningDevices
registerDeviceForEpollLocked最终调用:

//frameworks\native\services\inputflinger\reader\EventHub.cpp
status_t EventHub::registerFdForEpoll(int fd) {
    // TODO(b/121395353) - consider adding EPOLLRDHUP
    struct epoll_event eventItem = {};
    eventItem.events = EPOLLIN | EPOLLWAKEUP;
    eventItem.data.fd = fd;
    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
        ALOGE("Could not add fd to epoll instance: %s", strerror(errno));
        return -errno;
    }
    return OK;
}

addDeviceLocked:

//frameworks\native\services\inputflinger\reader\EventHub.cpp
void EventHub::addDeviceLocked(Device* device) {
    mDevices.add(device->id, device);
    device->next = mOpeningDevices;
    mOpeningDevices = device;
}

scanDevicesLocked就是扫描dev/input/这个目录并打开里面的设备节点,添加到epoll中监测(后续某个设备有输入数据时,epoll_wait会返回)。对于每个设备节点都会新建device,设置其classes,然后添加到mDevices集合中。
前面提到过,scanDevicesLocked执行完成后,就是构建event,然后getEvents方法返回,回到InputReader的loopOnce方法,继续执行processEventsLocked处理这些event

//frameworks\native\services\inputflinger\reader\InputReader.cpp
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        int32_t type = rawEvent->type;
        size_t batchSize = 1;
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {//type 为DEVICE_ADDED或者FINISHED_DEVICE_SCAN,不走这个分支
            //省略
        } else {
            switch (rawEvent->type) {
                case EventHubInterface::DEVICE_ADDED:
                    addDeviceLocked(rawEvent->when, rawEvent->deviceId);//1
                    break;
                case EventHubInterface::DEVICE_REMOVED:
                    removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
                    break;
                case EventHubInterface::FINISHED_DEVICE_SCAN:
                    handleConfigurationChangedLocked(rawEvent->when);
                    break;
                default:
                    ALOG_ASSERT(false); // can't happen
                    break;
            }
        }
        count -= batchSize;
        rawEvent += batchSize;
    }
}

对于type为DEVICE_ADDED的event,调用addDeviceLocked处理

//frameworks\native\services\inputflinger\reader\InputReader.cpp
void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
    if (mDevices.find(eventHubId) != mDevices.end()) {
        ALOGW("Ignoring spurious device added event for eventHubId %d.", eventHubId);
        return;
    }

    InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
    std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
	//省略
}

继续调用createDeviceLocked创建InputDevice对象

//frameworks\native\services\inputflinger\reader\InputReader.cpp
std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
        int32_t eventHubId, const InputDeviceIdentifier& identifier) {
    auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {
        return devicePair.second->getDescriptor().size() && identifier.descriptor.size() &&
                devicePair.second->getDescriptor() == identifier.descriptor;
    });

    std::shared_ptr<InputDevice> device;
    if (deviceIt != mDevices.end()) {
        device = deviceIt->second;
    } else {
        int32_t deviceId = (eventHubId < END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();
        device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),
                                               identifier);//1
    }
    device->addEventHubDevice(eventHubId);//2
    return device;
}

注释1处创建InputDevice,注释2处调用其addEventHubDevice方法

//frameworks\native\services\inputflinger\reader\InputDevice.cpp
void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
	//省略
	// Touchscreens and touchpad devices.
    if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
        mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));//1
    } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
        mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
    }
	//省略
	// insert the context into the devices set
    mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});//2
}

注释1处,对于多指触摸,设置其mapper为MultiTouchInputMapper,注释2处添加到mDevices集合中。
对于开机已存在的输入设备已经处理完了。主要是扫描并打开这些设备,添加到epoll中,监听这些设备有无事件发生,然后创建InputDevice,根据不同的设备设置其mapper。

处理新增或者移除的输入设备
在平时没有事件时,在EventHub方法中

//frameworks\native\services\inputflinger\reader\EventHub.cpp
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
	if (event != buffer || awoken) {//没有事件这个不会返回,函数继续往下执行
            break;
     }
	int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
	//省略
}

通过epoll_wait等待事件,而在Android11 InputManagerService启动流程分析 一文中提到,EventHub在初始化的时候,初始化inotify来监听dev/input目录,并使用epoll监听这个inotify。
假设现在有设备新增,则这个epoll_wait会返回,getEvents继续往下执行

//frameworks\native\services\inputflinger\reader\EventHub.cpp
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
	
	int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);

    if (pollResult < 0) {
          
     } else {
     	// Some events occurred.
		 mPendingEventCount = size_t(pollResult);
	}
}

设置了mPendingEventCount ,继续执行下一次循环

//frameworks\native\services\inputflinger\reader\EventHub.cpp
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
	//省略
	while (mPendingEventIndex < mPendingEventCount) {//这时候,这个条件满足
            const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
            if (eventItem.data.fd == mINotifyFd) {//有设备增加或删除
                if (eventItem.events & EPOLLIN) {
                    mPendingINotify = true;//设置mPendingINotify 为ture
                } else {
                    ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
                }
                continue;//跳出循环
            }
            //省略
     }
	// readNotify() will modify the list of devices so this must be done after
        // processing all other events to ensure that we read all remaining events
        // before closing the devices.
  	if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {//满足条件
            mPendingINotify = false;
            readNotifyLocked();//1
            deviceChanged = true;
 	}
}

有设备增加或删除时,调用注释1处的readNotifyLocked处理

status_t EventHub::readNotifyLocked() {
    int res;
    char event_buf[512];
    int event_size;
    int event_pos = 0;
    struct inotify_event* event;

    ALOGV("EventHub::readNotify nfd: %d\n", mINotifyFd);
    res = read(mINotifyFd, event_buf, sizeof(event_buf));//读取数据
    
    while (res >= (int)sizeof(*event)) {
        event = (struct inotify_event*)(event_buf + event_pos);
        if (event->len) {
            if (event->wd == mInputWd) {
                std::string filename = StringPrintf("%s/%s", DEVICE_PATH, event->name);
                if (event->mask & IN_CREATE) {
                    openDeviceLocked(filename.c_str());//1
                } else {
                    ALOGI("Removing device '%s' due to inotify event\n", filename.c_str());
                    closeDeviceByPathLocked(filename.c_str());
                }
            } else if (event->wd == mVideoWd) {
               //省略
            } else {
                LOG_ALWAYS_FATAL("Unexpected inotify event, wd = %i", event->wd);
            }
        }
        event_size = sizeof(*event) + event->len;
        res -= event_size;
        event_pos += event_size;
    }
    return 0;
}

注释1处也是调用openDeviceLocked来处理,openDeviceLocked前面分析过。

关于设备的处理,可以用一张图来总结

在这里插入图片描述
对输入设备产生的输入数据进行处理

和监听输入设备的添加一样,当有输入数据来的时候,getEvents方法中,epoll_wait会返回,设置mPendingEventCount的值,然后进入getEvents下次循环

//frameworks\native\services\inputflinger\reader\EventHub.cpp
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
	//省略
	for (;;) {
		//省略
		while (mPendingEventIndex < mPendingEventCount) {//前面设置了mPendingEventCount,满足条件
			const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
			//省略
			Device* device = getDeviceByFdLocked(eventItem.data.fd);//根据产生事件设备的fd,找到device 
			//省略
			// This must be an input event
            if (eventItem.events & EPOLLIN) {
            	int32_t readSize = read(device->fd, readBuffer, sizeof(struct input_event) * capacity);//读取数据
                	//省略
                    int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;

                    size_t count = size_t(readSize) / sizeof(struct input_event);
                    for (size_t i = 0; i < count; i++) {
                        struct input_event& iev = readBuffer[i];
                        event->when = processEventTimestamp(iev);
                        event->deviceId = deviceId;
                        event->type = iev.type;
                        event->code = iev.code;
                        event->value = iev.value;
                        event += 1;
                        capacity -= 1;
                    }
                    if (capacity == 0) {
                        // The result buffer is full.  Reset the pending event index
                        // so we will try to read the device again on the next iteration.
                        mPendingEventIndex -= 1;
                        break;
       			//省略
		}
		
		// Return now if we have collected any events or if we were explicitly awoken.
        if (event != buffer || awoken) {//跳出循环
            break;
        }
	}
}

对于设备产生的输入数据,也是构造RawEvent,只不过这些event的type为驱动上报的type,如:ABS_MT_POSITION_X 。
同样,跳出getEvents循环后,调用processEventsLocked来处理这些RawEvent

//frameworks\native\services\inputflinger\reader\InputReader.cpp
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        int32_t type = rawEvent->type;
        size_t batchSize = 1;
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {//输入事件的type肯定远小于0x10000000,满足条件
            int32_t deviceId = rawEvent->deviceId;
            while (batchSize < count) {
                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT ||
                    rawEvent[batchSize].deviceId != deviceId) {
                    break;
                }
                batchSize += 1;
            }
            
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);//1

	//省略

对于输入事件,继续调用注释1处的processEventsForDeviceLocked处理

//frameworks\native\services\inputflinger\reader\InputReader.cpp
void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,
                                               size_t count) {
    auto deviceIt = mDevices.find(eventHubId);//取出InputDevice
   
    std::shared_ptr<InputDevice>& device = deviceIt->second;
    if (device->isIgnored()) {//如果这个设备没有设置过mappers数组的话,就忽略这个设备
        // ALOGD("Discarding event for ignored deviceId %d.", deviceId);
        return;
    }

    device->process(rawEvents, count);//1
}

找到InputDevice之后,继续调用其process进行处理

//frameworks\native\services\inputflinger\reader\InputDevice.cpp
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
   
    for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
        if (mDropUntilNextSync) {
            	//省略
            } else {
				//省略
            }
        } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
            //省略
        } else {
            for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
                mapper.process(rawEvent);
            });
        }
        --count;
    }
}

找出InputDevice对应的mapper(之前在处理输入设备的时候,设置过mappers集合),调用这些mapper的process方法。对于多指触摸屏,mapper为MultiTouchInputMapper

//frameworks\native\services\inputflinger\reader\mapper\MultiTouchInputMapper.cpp
void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
    TouchInputMapper::process(rawEvent);//1,处理type为EV_SYN,code为SYN_REPORT的事件

    mMultiTouchMotionAccumulator.process(rawEvent);
}

EV_SYN同步事件是在一个event结束时驱动上报的。比如下面的触摸协议:

EV_ABS       ABS_MT_SLOT          00000000        
EV_ABS       ABS_MT_TRACKING_ID   00000016        
EV_KEY       BTN_TOUCH            DOWN           
EV_KEY       BTN_TOOL_FINGER      DOWN                
EV_ABS       ABS_MT_POSITION_X    0000011a       
EV_ABS       ABS_MT_POSITION_Y    00000475       
EV_ABS       ABS_MT_TOUCH_MAJOR   00000003      
EV_SYN       SYN_REPORT           00000000    

对于其它类型的数据,调用mMultiTouchMotionAccumulator的process处理,先来看一下这个方法

//frameworks\native\services\inputflinger\reader\mapper\MultiTouchInputMapper.cpp
void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
    if (rawEvent->type == EV_ABS) {//处理type为EV_ABS的数据
        bool newSlot = false;
        if (mUsingSlotsProtocol) {//这个值一般为true
            if (rawEvent->code == ABS_MT_SLOT) {
                mCurrentSlot = rawEvent->value;
                newSlot = true;
            }
        } else if (mCurrentSlot < 0) {
            mCurrentSlot = 0;
        }

        if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
			//省略
        } else {
            Slot* slot = &mSlots[mCurrentSlot];

            switch (rawEvent->code) {
                case ABS_MT_POSITION_X:
                    slot->mInUse = true;
                    slot->mAbsMTPositionX = rawEvent->value;
                    break;
                case ABS_MT_POSITION_Y:
                    slot->mInUse = true;
                    slot->mAbsMTPositionY = rawEvent->value;
                    break;
                case ABS_MT_TOUCH_MAJOR:
                    slot->mInUse = true;
                    slot->mAbsMTTouchMajor = rawEvent->value;
                    break;
                case ABS_MT_TOUCH_MINOR:
                    slot->mInUse = true;
                    slot->mAbsMTTouchMinor = rawEvent->value;
                    slot->mHaveAbsMTTouchMinor = true;
                    break;
                case ABS_MT_WIDTH_MAJOR:
                    slot->mInUse = true;
                    slot->mAbsMTWidthMajor = rawEvent->value;
                    break;
                case ABS_MT_WIDTH_MINOR:
                    slot->mInUse = true;
                    slot->mAbsMTWidthMinor = rawEvent->value;
                    slot->mHaveAbsMTWidthMinor = true;
                    break;
                case ABS_MT_ORIENTATION:
                    slot->mInUse = true;
                    slot->mAbsMTOrientation = rawEvent->value;
                    break;
                case ABS_MT_TRACKING_ID:
                    if (mUsingSlotsProtocol && rawEvent->value < 0) {
                        // The slot is no longer in use but it retains its previous contents,
                        // which may be reused for subsequent touches.
                        slot->mInUse = false;
                    } else {
                        slot->mInUse = true;
                        slot->mAbsMTTrackingId = rawEvent->value;
                    }
                    break;
                case ABS_MT_PRESSURE:
                    slot->mInUse = true;
                    slot->mAbsMTPressure = rawEvent->value;
                    break;
                case ABS_MT_DISTANCE:
                    slot->mInUse = true;
                    slot->mAbsMTDistance = rawEvent->value;
                    break;
                case ABS_MT_TOOL_TYPE:
                    slot->mInUse = true;
                    slot->mAbsMTToolType = rawEvent->value;
                    slot->mHaveAbsMTToolType = true;
                    break;
            }
        }
    } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {//code一般为
        // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
        mCurrentSlot += 1;
    }
}

可以看出该方法,就是处理type为EV_ABS的数据,填充slot。对于code为ABS_MT_SLOT,则认为是一个新手指,新建slot。经过这个方法的处理,数据都放入mSlots里面了。
最后上报的是EV_SYN同步事件,回到MultiTouchInputMapper的process方法,对于同步事件,调用TouchInputMapper的process处理

//frameworks\native\services\inputflinger\reader\mapper\TouchInputMapper.cpp
void TouchInputMapper::process(const RawEvent* rawEvent) {
    //省略

    if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
        sync(rawEvent->when);
    }
}

继续调用sync处理

//frameworks\native\services\inputflinger\reader\mapper\TouchInputMapper.cpp
void TouchInputMapper::sync(nsecs_t when) {
    const RawState* last =
            mRawStatesPending.empty() ? &mCurrentRawState : &mRawStatesPending.back();

    // Push a new state.
    mRawStatesPending.emplace_back();//往mRawStatesPending的尾部插入一个空的RawState
	
    RawState* next = &mRawStatesPending.back();//将next指向mRawStatesPending的最后一个
    next->clear();
    next->when = when;

   //省略

    // Sync touch
    syncTouch(when, next);//1

    // Assign pointer ids.
    if (!mHavePointerIds) {
        assignPointerIds(last, next);
    }
	
    processRawTouches(false /*timeout*/);//2
}

注释1处填充next(next为RawState对象),即填充mRawStatesPending,注释2处开始处理数据。先来看一下syncTouch方法

//frameworks\native\services\inputflinger\reader\mapper\MultiTouchInputMapper.cpp
void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
    size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
    size_t outCount = 0;
    BitSet32 newPointerIdBits;
    mHavePointerIds = true;

    for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
        const MultiTouchMotionAccumulator::Slot* inSlot =
                mMultiTouchMotionAccumulator.getSlot(inIndex);//遍历取出Slot
        if (!inSlot->isInUse()) {
            continue;
        }
        //省略
        /*根据slot的数据,开始填充RawState*/
        RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
        outPointer.x = inSlot->getX();
        outPointer.y = inSlot->getY();
        outPointer.pressure = inSlot->getPressure();
        outPointer.touchMajor = inSlot->getTouchMajor();
        outPointer.touchMinor = inSlot->getTouchMinor();
        outPointer.toolMajor = inSlot->getToolMajor();
        outPointer.toolMinor = inSlot->getToolMinor();
        outPointer.orientation = inSlot->getOrientation();
        outPointer.distance = inSlot->getDistance();
        outPointer.tiltX = 0;
        outPointer.tiltY = 0;

        outPointer.toolType = inSlot->getToolType();
        //省略
        /*开始处理id和index*/
        // Assign pointer id using tracking id if available.
        if (mHavePointerIds) {
            int32_t trackingId = inSlot->getTrackingId();
            int32_t id = -1;
            if (trackingId >= 0) {
                for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty();) {
                    uint32_t n = idBits.clearFirstMarkedBit();
                    if (mPointerTrackingIdMap[n] == trackingId) {
                        id = n;
                    }
                }

                if (id < 0 && !mPointerIdBits.isFull()) {
                    id = mPointerIdBits.markFirstUnmarkedBit();
                    mPointerTrackingIdMap[id] = trackingId;
                }
            }
            if (id < 0) {
                mHavePointerIds = false;
                outState->rawPointerData.clearIdBits();
                newPointerIdBits.clear();
            } else {
                outPointer.id = id;
                outState->rawPointerData.idToIndex[id] = outCount;
                outState->rawPointerData.markIdBit(id, isHovering);
                newPointerIdBits.markBit(id);
            }
        }
        outCount += 1;
    }

    outState->rawPointerData.pointerCount = outCount;
    mPointerIdBits = newPointerIdBits;

    mMultiTouchMotionAccumulator.finishSync();//清空Slot
}

在syncTouch方法中,除了填充RawState,还有对id和index的处理,可以看出id和index不一定相等。在多指的开发中注意,只有id才能代表一个手指,需要根据id,从idToIndex中得到index,从而找到对应的触摸信息。

继续回到sync方法,syncTouch处理完成后,调用processRawTouches继续处理数据

//frameworks\native\services\inputflinger\reader\mapper\TouchInputMapper.cpp
void TouchInputMapper::processRawTouches(bool timeout) {
    //省略
    const size_t N = mRawStatesPending.size();//前面已经填充过mRawStatesPending了,这里取出来
    size_t count;
    for (count = 0; count < N; count++) {
        const RawState& next = mRawStatesPending[count];//遍历取出RawState
		//省略
        mCurrentRawState.copyFrom(next);//将数据拷贝到mCurrentRawState中
        if (mCurrentRawState.when < mLastRawState.when) {
            mCurrentRawState.when = mLastRawState.when;
        }
        cookAndDispatch(mCurrentRawState.when);//1
    }
    if (count != 0) {
        mRawStatesPending.erase(mRawStatesPending.begin(), mRawStatesPending.begin() + count);//处理完之后要擦除
    }
   //省略
    
}

注释1处调用cookAndDispatch方法来处理以及分发数据

//frameworks\native\services\inputflinger\reader\mapper\TouchInputMapper.cpp
void TouchInputMapper::cookAndDispatch(nsecs_t when) {
	mCurrentCookedState.clear();
	//省略
	cookPointerData();//1
	if (mDeviceMode == DEVICE_MODE_POINTER) {
		//省略
	}else{
		if (!mCurrentMotionAborted) {
            dispatchButtonRelease(when, policyFlags);
            dispatchHoverExit(when, policyFlags);
            dispatchTouches(when, policyFlags);//2
            dispatchHoverEnterAndMove(when, policyFlags);
            dispatchButtonPress(when, policyFlags);
        }
	}
	//省略
	// Copy current touch to last touch in preparation for the next cycle.
    mLastRawState.copyFrom(mCurrentRawState);//将这次的数据拷贝到mLastRawState
    mLastCookedState.copyFrom(mCurrentCookedState);//拷贝数据
}

注释1处cookPointerData方法比较长,主要是对数据进行加工,加工后的数据放入mCurrentCookedState中。为什么要进行加工呢?因为当前的数据,比如X,Y坐标还是针对触摸屏的,我们要加工成显示屏上对应的坐标
注释2处开始分发数据了,主要是根据不同的情况调用dispatchMotion,分发AMOTION_EVENT_ACTION_MOVE,AMOTION_EVENT_ACTION_POINTER_UP和 AMOTION_EVENT_ACTION_POINTER_DOWN 的 action
接着直接来看下dispatchMotion

//frameworks\native\services\inputflinger\reader\mapper\TouchInputMapper.cpp
void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
                                      int32_t action, int32_t actionButton, int32_t flags,
                                      int32_t metaState, int32_t buttonState, int32_t edgeFlags,
                                      const PointerProperties* properties,
                                      const PointerCoords* coords, const uint32_t* idToIndex,
                                      BitSet32 idBits, int32_t changedId, float xPrecision,
                                      float yPrecision, nsecs_t downTime) {
    PointerCoords pointerCoords[MAX_POINTERS];
    PointerProperties pointerProperties[MAX_POINTERS];
    uint32_t pointerCount = 0;
    while (!idBits.isEmpty()) {
        uint32_t id = idBits.clearFirstMarkedBit();
        uint32_t index = idToIndex[id];
        pointerProperties[pointerCount].copyFrom(properties[index]);
        pointerCoords[pointerCount].copyFrom(coords[index]);//拷贝,coords包含了坐标信息等数据

        if (changedId >= 0 && id == uint32_t(changedId)) {
            action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
        }

        pointerCount += 1;
    }

    ALOG_ASSERT(pointerCount != 0);

    if (changedId >= 0 && pointerCount == 1) {
    	/*可以看出,如果是第一根手指,这里做了处理,变成AMOTION_EVENT_ACTION_DOWN和AMOTION_EVENT_ACTION_UP*/
        if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
            action = AMOTION_EVENT_ACTION_DOWN;
        } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
            action = AMOTION_EVENT_ACTION_UP;
        } else {
            // Can't happen.
            ALOG_ASSERT(false);
        }
    }
    //省略
    NotifyMotionArgs args(getContext()->getNextId(), when, deviceId, source, displayId, policyFlags,
                          action, actionButton, flags, metaState, buttonState,
                          MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties,
                          pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
                          downTime, std::move(frames));//1
    getListener()->notifyMotion(&args);//2
}

注释1处又将数据构造成了一个NotifyMotionArgs 对象。注释2处这个getListener()返回的是什么呢?返回的是一个QueuedInputListener对象。具体参考这张简易的类图
在这里插入图片描述

调用QueuedInputListener的notifyMotion方法

//frameworks\native\services\inputflinger\InputListener.cpp
void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
    traceEvent(__func__, args->id);
    mArgsQueue.push_back(new NotifyMotionArgs(*args));
}

这里只是将数据放入了队列。在InputReader线程中,最后会调用flush方法,来处理这个队列

//frameworks\native\services\inputflinger\InputListener.cpp
void QueuedInputListener::flush() {
    size_t count = mArgsQueue.size();
    for (size_t i = 0; i < count; i++) {
        NotifyArgs* args = mArgsQueue[i];
        args->notify(mInnerListener);//1
        delete args;
    }
    mArgsQueue.clear();
}

遍历队列,注释1处调用NotifyMotionArgs的notify方法,注意传入的参数为mInnerListener,mInnerListener指向的是一个InputClassifier对象(看上图)

//frameworks\native\services\inputflinger\InputListener.cpp
void NotifyMotionArgs::notify(const sp<InputListenerInterface>& listener) const {
    listener->notifyMotion(this);
}

直接调用InputClassifier的notifyMotion方法

//frameworks\native\services\inputflinger\InputClassifier.cpp
void InputClassifier::notifyMotion(const NotifyMotionArgs* args) {
    std::scoped_lock lock(mLock);
    //省略

    NotifyMotionArgs newArgs(*args);
    newArgs.classification = mMotionClassifier->classify(newArgs);
    mListener->notifyMotion(&newArgs);//mListener是InputDispatcher
}

调用InputDispatcher的notifyMotion方法

//frameworks\native\services\inputflinger\dispatcher\InputDispatcher.cpp
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
	//省略
	mPolicy->interceptMotionBeforeQueueing(args->displayId, args->eventTime, /*byref*/ policyFlags);//1
	bool needWake;
    { // acquire lock
        mLock.lock();
        if (shouldSendMotionToInputFilterLocked(args)) {//可以设置拦截器直接处理
			//省略
		}
		// Just enqueue a new motion event.
        MotionEntry* newEntry =
                new MotionEntry(args->id, args->eventTime, args->deviceId, args->source,
                                args->displayId, policyFlags, args->action, args->actionButton,
                                args->flags, args->metaState, args->buttonState,
                                args->classification, args->edgeFlags, args->xPrecision,
                                args->yPrecision, args->xCursorPosition, args->yCursorPosition,
                                args->downTime, args->pointerCount, args->pointerProperties,
                                args->pointerCoords, 0, 0);//2

        needWake = enqueueInboundEventLocked(newEntry);//3
        mLock.unlock();
    } // release lock

    if (needWake) {
        mLooper->wake();//4
    }
}

注释1处通过JNI调用到Java层的interceptMotionBeforeQueueingNonInteractive方法,注释2处又将数据封装成了MotionEntry对象,注释3处入“iq”队列,注释4处虽然这个是在InputDispatcher中,但实际上还是在InputReader线程中调用的,所以需要唤醒InputDispatcher线程。

//frameworks\native\services\inputflinger\dispatcher\InputDispatcher.cpp
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
    bool needWake = mInboundQueue.empty();
    mInboundQueue.push_back(entry);//放入iq队列
    traceInboundQueueLengthLocked();//这就是为什么可以在trace中看到iq的原因
	//省略

    return needWake;
}

到这里,InputReader的工作就完成了,接下来就是InputDispatcher线程的处理了。对于多指触摸,总结下InputReader处理数据的流程
在这里插入图片描述

  • 25
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值