InputReader源码分析
版本:android 13
一. 线程的创建及启动
接着InputManager的启动流程分析,在调用InManager的start方法后调用了NativeInputManager的start方法
public void start() {
Slog.i(TAG, "Starting input manager");
// 调用start,启动线程
mNative.start();
// ... 省略
}
这是一个native的方法,跟进去:com_*android_*server_input_InputManagerService.cpp
// java层mNative.start();调用到这里,这里很巧妙,这个nativeImplObj就是mNative,而这个mNative就是上面返回给java的地址im,通过调用native方法,自动的又传回来了,妙啊
static void nativeStart(JNIEnv* env, jobject nativeImplObj) {
// 获取到NativeInputManager
NativeInputManager* im = getNativeInputManager(env, nativeImplObj);
// 获取InputManager,然后调用start方法启动线程
status_t result = im->getInputManager()->start();
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
代码的作用看上面的注释,很详细了,继续我们去看InputManager的start方法InputManager.cpp
status_t InputManager::start() {
// ... 省略
result = mReader->start();
// ... 省略
return OK;
}
继续看InputReader的start方法InputReader.cpp
status_t InputReader::start() {
if (mThread) {
return ALREADY_EXISTS;
}
mThread = std::make_unique<InputThread>(
"InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
return OK;
}
这里创建了一个线程,和9.0的代码不太一样,9.0的代码是在构造的时候就创建了,这里是启动的时候就创建了,而且是unique_ptr的独享智能指针
继续看它里面的参数: 这里看可能不是很好看,熟悉C++的都知道,unique_ptr是一个模板,所以我们直接去看这个InputThread的构造函数
class InputThread {
public:
// explicit 作用,防止隐式类型转换的方式初始化对象
explicit InputThread(std::string name, std::function<void()> loop,
std::function<void()> wake = nullptr);
virtual ~InputThread();
bool isCallingThread();
private:
std::string mName;
std::function<void()> mThreadWake;
sp<Thread> mThread;
};
这里就比较好看出它的参数是什么了,第一个是线程名,第二个应该是线程执行的函数,第三个应该是唤醒用的函数,我们具体再看一下这个类的实现
// 构造函数的实现,我们可以看到,第一个name是赋值给了mName,第二个loop是通过new InputThreadImpl(loop),构造出来的,最后赋值给了mThread
// mThread是一个sp<Thread>,是一个线程,所以,loop我们可以确定是InputReaderThread的线程函数,而且在构造完成之后直接调用了mThread的run方法
// 第三个,也是一个函数,直接赋值给了mThreadWake,可以看到,在InputThread析构的时候调用了mThreadWake方法,有可能是为了自己唤醒自己的,这里暂时这么猜测。
InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
: mName(name), mThreadWake(wake) {
mThread = new InputThreadImpl(loop);
mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}
InputThread::~InputThread() {
mThread->requestExit();
if (mThreadWake) {
mThreadWake();
}
mThread->requestExitAndWait();
}
bool InputThread::isCallingThread() {
return gettid() == mThread->getTid();
}
下面就是线程的实现了
// Implementation of Thread from libutils.
class InputThreadImpl : public Thread {
public:
explicit InputThreadImpl(std::function<void()> loop)
: Thread(/* canCallJava */ true), mThreadLoop(loop) {}
~InputThreadImpl() {}
private:
std::function<void()> mThreadLoop;
bool threadLoop() override {
mThreadLoop();
return true;
}
};
它继承了Thread类重写了threadLooper,当我们调用run的时候会执行字方法,ok,到此为止线程的创建及启动就完成了,接下来我们分析线程函数是如何工作的。
二. 线程函数的执行
// 这是InputReader的构造函数,因为线程函数有很多判断依赖这个里面的变量的值,方这里方便查看
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
const sp<InputReaderPolicyInterface>& policy,
InputListenerInterface& listener)
: mContext(this),
mEventHub(eventHub),
mPolicy(policy),
mQueuedListener(listener),
mGlobalMetaState(AMETA_NONE),
mLedMetaState(AMETA_NONE),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
}
// 当make_unique<InputThread>执行完之后,这个函数就会被调用执行。
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
std::vector<InputDeviceInfo> inputDevices;
{ // acquire lock
std::scoped_lock _l(mLock);
// 这个值默认为1,暂时不知道干啥的,先放着
oldGeneration = mGeneration;
timeoutMillis = -1;
// 这个值在构造里面被赋值为0所以下面的if不会进去,暂时不看
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
mConfigurationChangesToRefresh = 0;
timeoutMillis = 0;
refreshConfigurationLocked(changes);
// mNextTimeout在构造函数中被赋值为LLONG_MAX,所以暂时不管
} else if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
} // release lock
// 重点函数,看名字感觉像是获取事件的个数的,我们下面重点分析它
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
// ... 省略,先分析getEents然后再往下分析
}
2.1 EentHub的getEvents解析
// 前面在分析InputManager的启动流程的时候已经分析过在构建EventHub的时候都做了什么事,这里再回忆一下,构造函数也对很多成员变量赋上了默认值,在我们分析getevents的时候会用到,放到这里也方便下面查看。
EventHub::EventHub(void)
: mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD),
mNextDeviceId(1),
mControllerNumbers(),
mNeedToSendFinishedDeviceScan(false),
mNeedToReopenDevices(false),
mNeedToScanDevices(true),
mPendingEventCount(0),
mPendingEventIndex(0),
mPendingINotify(false) {
ensureProcessCanBlockSuspend();
// ... 代码省略
// 主要就是创建了epoll和初始化了inotify,将/dev/input目录添加到inotify的监听,然后通过epoll监听inotify的fd进行处理/dev/input目录的文件变化,猜测是为了监听热插拔事件吧,先这么猜测。
}
//The event queue.下面两行是EentHub的两个成员,mEventBuffer是一个容量为256,成员类型为RawEent的数组
// static const int EVENT_BUFFER_SIZE = 256;
// RawEvent mEventBuffer[EVENT_BUFFER_SIZE] GUARDED_BY(mLock);
// 下面就是getEents函数了,它有三个参数,是上面传进来的,分别是: -1, 一个容量256的RawEent的数组,256
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
// ... 省略
// 这里创建了一个input_event的数组,大小是buffersize具体为了干啥暂时不知道,先往后看
struct input_event readBuffer[bufferSize];
// 弄了一个局部的指针指向了传进来的buffer
RawEvent* event = buffer;
// 给传进来的buffersize保存一下
size_t capacity = bufferSize;
bool awoken = false;
for (;;) {
// 当前的时间
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
// Reopen input devices if needed.
// 看构造函数,默认为false,所以,这里进不去
if (mNeedToReopenDevices) {
mNeedToReopenDevices = false;
ALOGI("Reopening all input devices due to a configuration change.");
closeAllDevicesLocked();
mNeedToScanDevices = true;
break; // return to the caller before we actually rescan
}
// 这里好像也进不去,第一次进来没有关闭的设备
// Report any devices that had last been added/removed.
for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) {
std::unique_ptr<Device> device = std::move(*it);
ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.c_str());
event->when = now;
event->deviceId = (device->id == mBuiltInKeyboardId)
? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
: device->id;
event->type = DEVICE_REMOVED;
event += 1;
it = mClosingDevices.erase(it);
mNeedToSendFinishedDeviceScan = true;
if (--capacity == 0) {
break;
}
}
// 看构造函数,这个为true,进去看
if (mNeedToScanDevices) {
mNeedToScanDevices = false;
// 看名字应该是扫描设备的。
scanDevicesLocked();
mNeedToSendFinishedDeviceScan = true;
}
// ... 省略,先分析上面的scanDevicesLocked()
}
2.2 scanDevicesLocked
void EventHub::scanDevicesLocked() {
status_t result;
std::error_code errorCode;
// 这里判断这个目录是否存在,如果存在则去扫描
if (std::filesystem::exists(DEVICE_INPUT_PATH, errorCode)) {
// 一般情况下,目录肯定存在的,所以走到这里
result = scanDirLocked(DEVICE_INPUT_PATH);
if (result < 0) {
ALOGE("scan dir failed for %s", DEVICE_INPUT_PATH);
}
} else {
if (errorCode) {
ALOGW("Could not run filesystem::exists() due to error %d : %s.", errorCode.value(),
errorCode.message().c_str());
}
}
// 视频相关,暂时不看
if (isV4lScanningEnabled()) {
result = scanVideoDirLocked(DEVICE_PATH);
if (result != OK) {
ALOGE("scan video dir failed for %s", DEVICE_PATH);
}
}
// 虚拟按键?暂时不看
if (mDevices.find(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) == mDevices.end()) {
createVirtualKeyboardLocked();
}
}
继续分析scanDirLocked
status_t EventHub::scanDirLocked(const std::string& dirname) {
// 遍历这个目录
for (const auto& entry : std::filesystem::directory_iterator(dirname)) {
// 打开这个设备
openDeviceLocked(entry.path());
}
return 0;
}
继续看openDeviceLocked
// 这个结构体用来标识一个设备
struct InputDeviceIdentifier {
inline InputDeviceIdentifier() :
bus(0), vendor(0), product(0), version(0) {
}
// 内核提供的信息
std::string name;
std::string location;
std::string uniqueId;
uint16_t bus;
uint16_t vendor;
uint16_t product;
uint16_t version;
// 唯一标识设备的复合输入设备描述符字符串,这个值一般不会变
std::string descriptor;
//如果没有id的时候用,应该是为了区分设备,暂时每弄明白,先放着
uint16_t nonce;
// 这大概是返回设备的名字?
std::string getCanonicalName() const;
};
// 打开一个设备
void EventHub::openDeviceLocked(const std::string& devicePath) {
// ... 容错信息,没看太懂,暂时先不看,先看主线
char buffer[80];
ALOGV("Opening device: %s", devicePath.c_str());
// 调用open函数打开设备
int fd = open(devicePath.c_str(), O_RDWR | O_CLOEXEC | O_NONBLOCK);
if (fd < 0) {
ALOGE("could not open %s, %s\n", devicePath.c_str(), strerror(errno));
return;
}
InputDeviceIdentifier identifier;
// 给驱动通信,获取名称
// Get device name.
if (ioctl(fd, EVIOCGNAME(sizeof(buffer) - 1), &buffer) < 1) {
ALOGE("Could not get device name for %s: %s", devicePath.c_str(), strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.name = buffer;
}
// ... 省略容错信息
// Get device driver version.
// 依旧是给驱动通信,获取版本信息
int driverVersion;
if (ioctl(fd, EVIOCGVERSION, &driverVersion)) {
ALOGE("could not get driver version for %s, %s\n", devicePath.c_str(), strerror(errno));
close(fd);
return;
}
// Get device identifier.
// 同样是和驱动通信,获取标识符
struct input_id inputId;
if (ioctl(fd, EVIOCGID, &inputId)) {
ALOGE("could not get device input id for %s, %s\n", devicePath.c_str(), strerror(errno));
close(fd);
return;
}
identifier.bus = inputId.bustype; // 总线类型
identifier.product = inputId.product; // 产品
identifier.vendor = inputId.vendor; // 制造商
identifier.version = inputId.version; // 版本
// Get device physical location.
// 获取设备的物理位置?
if (ioctl(fd, EVIOCGPHYS(sizeof(buffer) - 1), &buffer) < 1) {
// fprintf(stderr, "could not get location for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.location = buffer;
}
// Get device unique id.
// 获取设备的唯一ID
if (ioctl(fd, EVIOCGUNIQ(sizeof(buffer) - 1), &buffer) < 1) {
// fprintf(stderr, "could not get idstring for %s, %s\n", devicePath, strerror(errno));
} else {
buffer[sizeof(buffer) - 1] = '\0';
identifier.uniqueId = buffer;
}
// Fill in the descriptor.
// 填充设备的描述符
assignDescriptorLocked(identifier);
// Allocate device. (The device object takes ownership of the fd at this point.)
// 创建一个设备对象
int32_t deviceId = mNextDeviceId++;
std::unique_ptr<Device> device = std::make_unique<Device>(fd, deviceId, devicePath, identifier);
ALOGV("add device %d: %s\n", deviceId, devicePath.c_str());
ALOGV(" bus: %04x\n"
" vendor %04x\n"
" product %04x\n"
" version %04x\n",
identifier.bus, identifier.vendor, identifier.product, identifier.version);
ALOGV(" name: \"%s\"\n", identifier.name.c_str());
ALOGV(" location: \"%s\"\n", identifier.location.c_str());
ALOGV(" unique id: \"%s\"\n", identifier.uniqueId.c_str());
ALOGV(" descriptor: \"%s\"\n", identifier.descriptor.c_str());
ALOGV(" driver: v%d.%d.%d\n", driverVersion >> 16, (driverVersion >> 8) & 0xff,
driverVersion & 0xff);
// Load the configuration file for the device.
// 加载设备的配置文件
device->loadConfigurationLocked();
bool hasBattery = false;
bool hasLights = false;
// Check the sysfs root path
// 检查sysfs的根路径
std::optional<std::filesystem::path> sysfsRootPath = getSysfsRootPath(devicePath.c_str());
if (sysfsRootPath.has_value()) {
std::shared_ptr<AssociatedDevice> associatedDevice;
for (const auto& [id, dev] : mDevices) {
if (device->identifier.descriptor == dev->identifier.descriptor &&
!dev->associatedDevice) {
associatedDevice = dev->associatedDevice;
}
}
if (!associatedDevice) {
associatedDevice = std::make_shared<AssociatedDevice>(sysfsRootPath.value());
}
hasBattery = associatedDevice->configureBatteryLocked();
hasLights = associatedDevice->configureLightsLocked();
device->associatedDevice = associatedDevice;
}
// Figure out the kinds of events the device reports.
// 确认一下设备是什么类型的,如果是某种类型的,那么这个掩码会被置位
device->readDeviceBitMask(EVIOCGBIT(EV_KEY, 0), device->keyBitmask);
device->readDeviceBitMask(EVIOCGBIT(EV_ABS, 0), device->absBitmask);
device->readDeviceBitMask(EVIOCGBIT(EV_REL, 0), device->relBitmask);
device->readDeviceBitMask(EVIOCGBIT(EV_SW, 0), device->swBitmask);
device->readDeviceBitMask(EVIOCGBIT(EV_LED, 0), device->ledBitmask);
device->readDeviceBitMask(EVIOCGBIT(EV_FF, 0), device->ffBitmask);
device->readDeviceBitMask(EVIOCGBIT(EV_MSC, 0), device->mscBitmask);
device->readDeviceBitMask(EVIOCGPROP(0), device->propBitmask);
// ... 忽略很多判断当前设备类型的代码
// 判断是否是一个触摸板,判断是否是一个多点触控的设备,一般情况下,我们的手机或者车机都是这种类型,不支持多点触控的很早就不存在了。
if (device->absBitmask.test(ABS_MT_POSITION_X) && device->absBitmask.test(ABS_MT_POSITION_Y)) {
// 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 (device->keyBitmask.test(BTN_TOUCH) || !haveGamepadButtons) {
// 满足条件,给classes或上touch和touch_mt
device->classes |= (InputDeviceClass::TOUCH | InputDeviceClass::TOUCH_MT);
}
}
// ... 省略判断是否有操纵杆的代码,一般手机和车机都没有
// ... 省略判断是否为加速计设备
// ... 省略检查设备是否有开关的代码
// ... 省略检查设备是否支持振动的代码
// 判断是否支持虚拟按键,以前的手机屏幕下有虚拟按键,如果支持,则配置它
if ((device->classes.test(InputDeviceClass::TOUCH))) {
// Load the virtual keys for the touch screen, if any.
// We do this now so that we can make sure to load the keymap if necessary.
bool success = device->loadVirtualKeyMapLocked();
if (success) {
device->classes |= InputDeviceClass::KEYBOARD;
}
}
// ... 省略判断是键盘,操纵杆,传感器时加载配置的代码
// ... 省略配置键盘的代码
// ... 省略容错代码
// 检查输入设备是否带电池
if (hasBattery) {
device->classes |= InputDeviceClass::BATTERY;
}
// 检查这个设备是否有可控的灯
if (hasLights) {
device->classes |= InputDeviceClass::LIGHT;
}
// 检查这个设备是否有麦克风
if (device->deviceHasMicLocked()) {
device->classes |= InputDeviceClass::MIC;
}
// 确认这个设备是外部的还是内部的
if (device->isExternalDeviceLocked()) {
device->classes |= InputDeviceClass::EXTERNAL;
}
// ... 省略键盘,操作杆,传感器相关代码
// 最重要的,将这个设备加入epoll
if (registerDeviceForEpollLocked(*device) != OK) {
return;
}
// 配置这个fd,好像不关触摸屏什么事
device->configureFd();
ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=%s, "
"configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
deviceId, fd, devicePath.c_str(), device->identifier.name.c_str(),
device->classes.string().c_str(), device->configurationFile.c_str(),
device->keyMap.keyLayoutFile.c_str(), device->keyMap.keyCharacterMapFile.c_str(),
toString(mBuiltInKeyboardId == deviceId));
// 将这个设备添加到已打开的向量中
addDeviceLocked(std::move(device));
}
void EventHub::addDeviceLocked(std::unique_ptr<Device> device) {
reportDeviceAddedForStatisticsLocked(device->identifier, device->classes);
mOpeningDevices.push_back(std::move(device));
}
ok,至此,设备打开完成了
我们总结一下openDeviceLocked主要作了什么
- 首先打开设备
- 从驱动里面获取一些这个设备的信息
- 创建一个 Device的对象
- 将从驱动里面获取的信息保存到这个对象中
- 确认这个设备的类型,保存到Device中
- 再确认一下设备的其他信息也一并保存
- 然后将这个设备的fd添加到epoll中进行监听
- 最后将这个设备添加到用来保存已经打开的设备的向量中
这是打开一个设备的逻辑,在scanDirLocked函数中有一个for循环,它会循环打开/dev/input目录下的所有设备,同样的步骤,将他们添加到保存已打开设备的向量中,扫描设备逻辑就是这样的。
扫描完设备之后我们就继续看getevents函数接下来的部分
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
// ... 省略
// 这里创建了一个input_event的数组,大小是buffersize具体为了干啥暂时不知道,先往后看
struct input_event readBuffer[bufferSize];
// 弄了一个局部的指针指向了传进来的buffer
RawEvent* event = buffer;
// 给传进来的buffersize保存一下
size_t capacity = bufferSize;
bool awoken = false;
for (;;) {
// 当前的时间
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
// Reopen input devices if needed.
// 看构造函数,默认为false,所以,这里进不去
if (mNeedToReopenDevices) {
mNeedToReopenDevices = false;
ALOGI("Reopening all input devices due to a configuration change.");
closeAllDevicesLocked();
mNeedToScanDevices = true;
break; // return to the caller before we actually rescan
}
// 这里好像也进不去,第一次进来没有关闭的设备
// Report any devices that had last been added/removed.
for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) {
// ... 省略不执行的代码
}
// 看构造函数,这个为true,进去看
if (mNeedToScanDevices) {
mNeedToScanDevices = false;
// 这里已经将扫描到的设备添加到mOpeningDevices中了
scanDevicesLocked();
mNeedToSendFinishedDeviceScan = true;
}
// ---------------------------设备扫描完成之后我们继续分析----------------------------
// 刚扫描完设备,这里不是empty的,这个while能进去
while (!mOpeningDevices.empty()) {
// 获取最后一个设备
std::unique_ptr<Device> device = std::move(*mOpeningDevices.rbegin());
// 从向量中删除它
mOpeningDevices.pop_back();
ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
// 还记得这个event吗?这个就是我们外面传进来的数组,我们在这将元素赋值
event->when = now;
event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
event->type = DEVICE_ADDED; // 新添加
event += 1; // 指针偏移
// ... 省略视频设备相关代码
// 将这个设备添加到mDevices这个map中,其中设备的id为key
auto [dev_it, inserted] = mDevices.insert_or_assign(device->id, std::move(device));
if (!inserted) {
ALOGW("Device id %d exists, replaced.", device->id);
}
mNeedToSendFinishedDeviceScan = true;
if (--capacity == 0) { // 数组容量自减
break;
}
}
// 以上代码执行完,mOpeningDevices中就没有元素了,event中和mDevices中保存了这些设备的信息
// 设备扫描完成之后将最后一个元素类型设置为FINISHED_DEVICE_SCAN
if (mNeedToSendFinishedDeviceScan) {
mNeedToSendFinishedDeviceScan = false;
event->when = now;
event->type = FINISHED_DEVICE_SCAN;
event += 1;
if (--capacity == 0) {
break;
}
}
// Grab the next input event.
bool deviceChanged = false;
// 第一次进来这两个值都是0所以这个while进步来
while (mPendingEventIndex < mPendingEventCount) {
// ... 省略不执行的代码
}
// ... 省略不执行的代码
// 初始值event是等于buffer的,但后面event添加了设备,指针往后偏移了,所以这两个值是不相等的,所以这里break出去了。
if (event != buffer || awoken) {
break;
}
// ... 省略不执行的代码
// All done, return the number of events we read.
// 这里返回事件的个数,其实就是指针的偏移了几次,这里只是第一次进去的执行的逻辑
return event - buffer;
}
我们现在总结一下第一次执行getEents这个函数主要做了什么
- 扫描/deve/input目录下的所有设备并打开
- 在打开后从驱动获取一些信息保存到Device对象中,然后将扫描到的设备保存到mOpeningDevices这个vector中
- 遍历mOpeningDevices这个vector将设备添加到buffer和EventHub的mDevices这个map中
- 然后返回个数
2.3 继续分析线程函数
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
std::vector<InputDeviceInfo> inputDevices;
{ // acquire lock
std::scoped_lock _l(mLock);
// 这个值默认为1,暂时不知道干啥的,先放着
oldGeneration = mGeneration;
timeoutMillis = -1;
// 这个值在构造里面被赋值为0所以下面的if不会进去,暂时不看
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
mConfigurationChangesToRefresh = 0;
timeoutMillis = 0;
refreshConfigurationLocked(changes);
// mNextTimeout在构造函数中被赋值为LLONG_MAX,所以暂时不管
} else if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
} // release lock
// 重点函数,这里返回的是设备的个数,具体逻辑看2.2分析
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
// ------------------- 接着分析 ------------------------
{ // acquire lock
std::scoped_lock _l(mLock);
// 条件变量,暂时不管
mReaderIsAliveCondition.notify_all();
// 这里一般不太会为0,所以会进来
if (count) {
processEventsLocked(mEventBuffer, count);
}
// ... 先分析processEventsLocked,下面的代码后面分析
}
// 处理events的函数
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
// 这里遍历rawEvents,根据上面的分析,这个rawEents中保存了扫描到的设备
for (const RawEvent* rawEvent = rawEvents; count;) {
// 获取设备的类型
int32_t type = rawEvent->type;
size_t batchSize = 1;
// FIRST_SYNTHETIC_EVENT 和 DEVICE_ADDED相等,我们之前扫描到的设备类型都是DEVICE_ADDED,所以这里不会走
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
// ... 省略不会执行的代码
} else {
// 对于之前的设备,我们的类型都是DEVICE_ADDED所以我们只需要看DEVICE_ADDED的case
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
// ... 省略不执行的代码
default:
ALOG_ASSERT(false); // can't happen
break;
}
}
count -= batchSize;
rawEvent += batchSize;
}
}
继续看addDeviceLocked
void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
// ... 省略容错代码
// 我们在打开设备的时候就保存设备的标识到Device中,所以这里可以直接获取到
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
// 根据id和identifiel创建InputDeice
std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
// ... 分析一下createDeviceLocked
}
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;
// 从map中获取这个设备,如果有则直接获取,没有就创建一个,第一次进来肯定是没有的,所以会走else
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);
}
// 然后调用addEventHubDevice,继续分析这个方法
device->addEventHubDevice(eventHubId);
return device;
}
// 添加EentHubDevice populateMappers默认为true
void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
// ... 省略容错代码
std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));
ftl::Flags<InputDeviceClass> classes = contextPtr->getDeviceClasses();
std::vector<std::unique_ptr<InputMapper>> mappers;
// ... 省略不会执行的代码
// ... 省略其他设备类型的判断,我们暂时只分析触摸屏的。
// 一般来讲我们都是多指触摸,所以是这个if,然后将这个
if (classes.test(InputDeviceClass::TOUCH_MT)) {
mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
}
// ... 省略其他设备的的代码
// insert the context into the devices set
// mDevices的定义: std::unordered_map<int32_t, DevicePair> mDevices 就是设备id和DevicePair,其中DevicePair包括了InputDeviceContext和mappers
// 其中每一个InputDeviceContext对应一个类型的事件但看起来也只可能有一个InputDeviceContext,一个Input
mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
// Must change generation to flag this device as changed
// 标记设备已更改
bumpGeneration();
}
继续分析addDeviceLocked
void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
// ... 省略容错代码
// 我们在打开设备的时候就保存设备的标识到Device中,所以这里可以直接获取到
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
// 根据id和identifiel创建InputDeice
std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
// 上面这句代码执行完成InputDevice就创建完成了,也将mapper和eventHubId关联起来了
device->configure(when, &mConfig, 0);
device->reset(when);
// 这里返回false,只要这个设备里面有mapper,就返回false,所以一般走else,就是打印,也没啥用
if (device->isIgnored()) {
ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s' "
"(ignored non-input device)",
device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str());
} else {
ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s',sources=0x%08x",
device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str(),
device->getSources());
}
// 没看懂
mDevices.emplace(eventHubId, device);
// Add device to device to EventHub ids map.
// 将InputDevice和eventHubId 的向量联系到一起,为什么又保存了一次
const auto mapIt = mDeviceToEventHubIdsMap.find(device);
if (mapIt == mDeviceToEventHubIdsMap.end()) {
std::vector<int32_t> ids = {eventHubId};
mDeviceToEventHubIdsMap.emplace(device, ids);
} else {
mapIt->second.push_back(eventHubId);
}
// Sensor input device is noisy, to save power disable it by default.
// Input device is classified as SENSOR when any sub device is a SENSOR device, check Eventhub
// device class to disable SENSOR sub device only.
// 默认将sensor关闭
if (mEventHub->getDeviceClasses(eventHubId).test(InputDeviceClass::SENSOR)) {
mEventHub->disableDevice(eventHubId);
}
}
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
std::vector<InputDeviceInfo> inputDevices;
{ // acquire lock
std::scoped_lock _l(mLock);
// 这个值默认为1,暂时不知道干啥的,先放着
oldGeneration = mGeneration;
timeoutMillis = -1;
// 这个值在构造里面被赋值为0所以下面的if不会进去,暂时不看
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
mConfigurationChangesToRefresh = 0;
timeoutMillis = 0;
refreshConfigurationLocked(changes);
// mNextTimeout在构造函数中被赋值为LLONG_MAX,所以暂时不管
} else if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
} // release lock
// 重点函数,这里返回的是设备的个数,具体逻辑看2.2分析
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
std::scoped_lock _l(mLock);
// 条件变量,暂时不管
mReaderIsAliveCondition.notify_all();
// 这里一般不太会为0,所以会进来
if (count) {
processEventsLocked(mEventBuffer, count);
}
// ... 省略不执行的代码
// 这里能进来,在添加设备时,这个mGeneration就改变了
if (oldGeneration != mGeneration) {
inputDevicesChanged = true;
inputDevices = getInputDevicesLocked();
}
} // release lock
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
// 发出一条消息,设备已更改,这个mPolicy是InputReader
mPolicy->notifyInputDevicesChanged(inputDevices);
}
// 这个是InputDispatcher
mQueuedListener.flush();
}
所以,第一次调用loopOnce都做了哪些事我们总结一下:
- 扫描设备,保存起来
- 获取设备信息,将mapper和设备关联起来
- 通知InputReader设备更改了
- 通知InputDispatcher刷新设备
由于这个是线程函数,threadLoop返回了true,所以这个函数会持续被调用
bool threadLoop() override {
mThreadLoop();
return true;
}
// 所以我们继续分析第二次进来的情况
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
std::vector<InputDeviceInfo> inputDevices;
{ // acquire lock
std::scoped_lock _l(mLock);
// 当设备没有改变时,这两个是相等的。
oldGeneration = mGeneration;
timeoutMillis = -1;
// 这个值在构造里面被赋值为0所以下面的if不会进去,暂时不看
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
mConfigurationChangesToRefresh = 0;
timeoutMillis = 0;
refreshConfigurationLocked(changes);
// mNextTimeout在构造函数中被赋值为LLONG_MAX,所以暂时不管
} else if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
} // release lock
// 重点函数,这里返回的是事件的个数,继续进去分析
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
// ... 省略,先分析第二次进去的情况
}
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
struct input_event readBuffer[bufferSize];
RawEvent* event = buffer;
size_t capacity = bufferSize;
bool awoken = false;
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
// 第二次进来也不需要扫描设备了。
// ... 省略不执行的代码
// Grab the next input event.
bool deviceChanged = false;
// epoll_wait执行完之后,一般这里就能进去了
while (mPendingEventIndex < mPendingEventCount) {
// 获取事件
const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
// 如果是inotify则给mPendingINotify设置为true,后面肯定会通知的。
if (eventItem.data.fd == mINotifyFd) {
if (eventItem.events & EPOLLIN) {
mPendingINotify = true;
} else {
ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
}
continue;
}
// ... 省略不是触摸屏的代码,我们暂时只分析触摸屏相关的。
// This must be an input event
// 判断这是否是一个可读的,也就是EPOLLIN,一般来讲,肯定是的。
if (eventItem.events & EPOLLIN) {
// 获取事件的个数
int32_t readSize =
read(device->fd, readBuffer, sizeof(struct input_event) * capacity);
// ... 省略容错代码一般走这个
else {
// 获取设备ID
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->readTime = systemTime(SYSTEM_TIME_MONOTONIC);
event->deviceId = deviceId;
event->type = iev.type;
event->code = iev.code;
event->value = iev.value;
event += 1;
capacity -= 1;
// ALOGE("jiangc event->when = %ld event->readTime = %ld event->deviceId = %d event->type = %d event->code = %d event->value = %d\n",
// (long)event->when, (long)event->readTime, event->deviceId, event->type, event->code, event->value);
}
}
}
// ... 省略容错代码
}
// 当处理完事件转化后,这两个数组又不一样了。
if (event != buffer || awoken) {
break;
}
// 赋值0
mPendingEventIndex = 0;
// 这里就是等待事件的发生,将发生的事件保存到mPendingEventItems中
int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);
mLock.lock(); // reacquire lock after poll
// 如果是0则没有事情发生
if (pollResult == 0) {
// Timed out.
mPendingEventCount = 0;
break;
}
// 小于0说明出错了
if (pollResult < 0) {
// An error occurred.
mPendingEventCount = 0;
// Sleep after errors to avoid locking up the system.
// Hopefully the error is transient.
if (errno != EINTR) {
ALOGW("poll failed (errno=%d)\n", errno);
usleep(100000);
}
} else {
// Some events occurred.
// 所以一般情况下,会走这里获取一下事件的个数,所以继续for循环,这里就不为0了
mPendingEventCount = size_t(pollResult);
}
}
// 读取到事件后,这里返回的是事件的个数
return event - buffer;
}
// 所以我们继续分析第二次进来的情况
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
std::vector<InputDeviceInfo> inputDevices;
{ // acquire lock
std::scoped_lock _l(mLock);
// 当设备没有改变时,这两个是相等的。
oldGeneration = mGeneration;
timeoutMillis = -1;
// 这个值在构造里面被赋值为0所以下面的if不会进去,暂时不看
uint32_t changes = mConfigurationChangesToRefresh;
if (changes) {
mConfigurationChangesToRefresh = 0;
timeoutMillis = 0;
refreshConfigurationLocked(changes);
// mNextTimeout在构造函数中被赋值为LLONG_MAX,所以暂时不管
} else if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
}
} // release lock
// 重点函数,这里返回的是发生事件的个数
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
std::scoped_lock _l(mLock);
mReaderIsAliveCondition.notify_all();
if (count) {
// 这次继续分析其他事件的处理逻辑
processEventsLocked(mEventBuffer, count);
}
}
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) {
// 获取设备id
int32_t deviceId = rawEvent->deviceId;
// 死循环获取一个设备的事件
while (batchSize < count) {
// 这里判断如果事件的deviceid变了,或者type大于FIRST_SYNTHETIC_EVENT,则说明不是一个device的事件要分开处理
if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT ||
rawEvent[batchSize].deviceId != deviceId) {
// 所以这里跳出while循环,先处理这个device的事件,之后再处理后续的事件
break;
}
batchSize += 1;
}
if (DEBUG_RAW_EVENTS) {
ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
}
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
}
// ... 省略,因为我们这次不是添加删除事件,所以这里不执行
count -= batchSize;
rawEvent += batchSize;
}
}
void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,
size_t count) {
// 查找这个设备
auto deviceIt = mDevices.find(eventHubId);
if (deviceIt == mDevices.end()) {
ALOGW("Discarding event for unknown eventHubId %d.", eventHubId);
return;
}
std::shared_ptr<InputDevice>& device = deviceIt->second;
if (device->isIgnored()) {
// ALOGD("Discarding event for ignored deviceId %d.", deviceId);
return;
}
// 去处理
device->process(rawEvents, count);
}
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
if (DEBUG_RAW_EVENTS) {
ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
rawEvent->when);
}
// 这个mDropUntilNextSync默认为false,构造函数中初始化的
if (mDropUntilNextSync) {
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
mDropUntilNextSync = false;
if (DEBUG_RAW_EVENTS) {
ALOGD("Recovered from input event buffer overrun.");
}
} else {
if (DEBUG_RAW_EVENTS) {
ALOGD("Dropped input event while waiting for next input sync.");
}
}
// 我们一般也不是SYN_DROPPED而是SYN_REPORT,所以这里也不会进
} else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
mDropUntilNextSync = true;
reset(rawEvent->when);
} else {
// 这里遍历这个设备的所有mapper去处理,我们暂时只看触摸的MultiTouchInputMapper
for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
mapper.process(rawEvent);
});
// 到这里,所有的mapper中都保存了相应的事件了。
}
--count;
}
}
// 以下是多指触控的日志
[ 1026.632366] /dev/input/event1: EV_SYN 0004 00000402 --同步头(其实理论上可以省略)
[ 1026.632366] /dev/input/event1: EV_SYN 0005 2576d0ba
[ 1026.632366] /dev/input/event1: EV_ABS ABS_MT_SLOT 00000000 代表第一个手指,其实第一个也可以没有,有的机器就第一次0是没有这个slot
[ 1026.632366] /dev/input/event1: EV_ABS ABS_MT_TRACKING_ID 00000016 第一个手指对应的TRACKING_ID
[ 1026.632366] /dev/input/event1: EV_ABS ABS_MT_POSITION_X 0000011a 按下X轴坐标
[ 1026.632366] /dev/input/event1: EV_ABS ABS_MT_POSITION_Y 00000475 按下Y轴坐标
[ 1026.632366] /dev/input/event1: EV_ABS ABS_MT_TOUCH_MAJOR 00000003 按下的椭圆长轴
[ 1026.632366] /dev/input/event1: EV_SYN SYN_REPORT 00000000 --同步尾(不省略)
[ 1027.937528] /dev/input/event1: EV_SYN 0004 00000403
[ 1027.937528] /dev/input/event1: EV_SYN 0005 37b18cde
[ 1027.937528] /dev/input/event1: EV_ABS ABS_MT_POSITION_X 0000011b 这里代表第一个手指移动后坐标
[ 1027.937528] /dev/input/event1: EV_ABS ABS_MT_POSITION_Y 00000476
[ 1027.937528] /dev/input/event1: EV_SYN SYN_REPORT 00000000
[ 1028.917333] /dev/input/event1: EV_SYN 0004 00000404
[ 1028.917333] /dev/input/event1: EV_SYN 0005 367d836c
[ 1028.917333] /dev/input/event1: EV_ABS ABS_MT_TOUCH_MINOR 00000003 这里是第一个手指的短轴,因为之前一直是slot为0
[ 1028.917333] /dev/input/event1: EV_ABS ABS_MT_SLOT 00000001 代表第二手指出来了
[ 1028.917333] /dev/input/event1: EV_ABS ABS_MT_TRACKING_ID 00000017 第二个手指对应TRACKING_ID
[ 1028.917333] /dev/input/event1: EV_ABS ABS_MT_POSITION_X 00000324 第二手指坐标
[ 1028.917333] /dev/input/event1: EV_ABS ABS_MT_POSITION_Y 00000165
[ 1028.917333] /dev/input/event1: EV_ABS ABS_MT_TOUCH_MAJOR 00000002
[ 1028.917333] /dev/input/event1: EV_ABS ABS_MT_TOUCH_MINOR 00000002 第二个手指短轴
[ 1028.917333] /dev/input/event1: EV_SYN SYN_REPORT 00000000
[ 1029.047446] /dev/input/event1: EV_SYN 0004 00000405
[ 1029.047446] /dev/input/event1: EV_SYN 0005 02afd368
[ 1029.047446] /dev/input/event1: EV_ABS ABS_MT_POSITION_Y 00000166 第二个手指坐标
[ 1029.047446] /dev/input/event1: EV_ABS ABS_MT_TOUCH_MAJOR 00000004
[ 1029.047446] /dev/input/event1: EV_ABS ABS_MT_TOUCH_MINOR 00000003
[ 1029.047446] /dev/input/event1: EV_SYN SYN_REPORT 00000000
void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
// EV_ABS为触控类型,所以我们可以进来
if (rawEvent->type == EV_ABS) {
// 标记是否是新的触点,开始肯定是false
bool newSlot = false;
// 是否是B版本的协议,一般是
if (mUsingSlotsProtocol) {
// 代表一个新的手指,这里更新值
if (rawEvent->code == ABS_MT_SLOT) {
mCurrentSlot = rawEvent->value;
newSlot = true;
}
} else if (mCurrentSlot < 0) {
mCurrentSlot = 0;
}
if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
if (DEBUG_POINTERS) {
if (newSlot) {
ALOGW("MultiTouch device emitted invalid slot index %d but it "
"should be between 0 and %zd; ignoring this slot.",
mCurrentSlot, mSlotCount - 1);
}
}
} else {
Slot* slot = &mSlots[mCurrentSlot];
// If mUsingSlotsProtocol is true, it means the raw pointer has axis info of
// ABS_MT_TRACKING_ID and ABS_MT_SLOT, so driver should send a valid trackingId while
// updating the slot.
if (!mUsingSlotsProtocol) {
slot->mInUse = true;
}
switch (rawEvent->code) {
case ABS_MT_POSITION_X: // X轴的位置
slot->mAbsMTPositionX = rawEvent->value;
warnIfNotInUse(*rawEvent, *slot);
break;
case ABS_MT_POSITION_Y: // Y轴的位置
slot->mAbsMTPositionY = rawEvent->value;
warnIfNotInUse(*rawEvent, *slot);
break;
case ABS_MT_TOUCH_MAJOR: // 按下的椭圆长轴
slot->mAbsMTTouchMajor = rawEvent->value;
break;
case ABS_MT_TOUCH_MINOR: // 按下的椭圆短轴
slot->mAbsMTTouchMinor = rawEvent->value;
slot->mHaveAbsMTTouchMinor = true;
break;
case ABS_MT_WIDTH_MAJOR:
slot->mAbsMTWidthMajor = rawEvent->value;
break;
case ABS_MT_WIDTH_MINOR:
slot->mAbsMTWidthMinor = rawEvent->value;
slot->mHaveAbsMTWidthMinor = true;
break;
case ABS_MT_ORIENTATION:
slot->mAbsMTOrientation = rawEvent->value;
break;
case ABS_MT_TRACKING_ID: 这里就是上面日至中的,tracking_id ,value,一般不会为0,为0说明不使用了,
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->mAbsMTPressure = rawEvent->value;
break;
case ABS_MT_DISTANCE:
slot->mAbsMTDistance = rawEvent->value;
break;
case ABS_MT_TOOL_TYPE:
slot->mAbsMTToolType = rawEvent->value;
slot->mHaveAbsMTToolType = true;
break;
}
}
} else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_MT_REPORT) {
// MultiTouch Sync: The driver has returned all data for *one* of the pointers.
mCurrentSlot += 1;
}
}
// 当所有的手指触摸事件都采集完成之后,就开始同步所有的事件状态
void TouchInputMapper::process(const RawEvent* rawEvent) {
mCursorButtonAccumulator.process(rawEvent);
mCursorScrollAccumulator.process(rawEvent);
mTouchButtonAccumulator.process(rawEvent);
// 这里代表一个手指的结束事件
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
sync(rawEvent->when, rawEvent->readTime);
}
}
void TouchInputMapper::sync(nsecs_t when, nsecs_t readTime) {
// 在末尾插入一个RawState
mRawStatesPending.emplace_back();
// 然后取出来最后一个,就是上面插入的。
RawState& next = mRawStatesPending.back();
// 清理
next.clear();
// 赋值时间
next.when = when;
next.readTime = readTime;
// ... 省略暂时不分析的。
// Sync touch
syncTouch(when, &next);
// ... 省略
}
void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
// 获取总共几个slot
size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
// 当前从第0个开始
size_t outCount = 0;
// 描述哪些位是被标记的,也就u是说当前这个地方有手指
BitSet32 newPointerIdBits;
mHavePointerIds = true;
// 遍历当前所有的slot
for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
// 获取第一个slot
const MultiTouchMotionAccumulator::Slot* inSlot =
mMultiTouchMotionAccumulator.getSlot(inIndex);
// 检查是否被使用,如果没有被使用则直接continue
if (!inSlot->isInUse()) {
continue;
}
// 获取触摸工具的类型,我们只讨论手指的,这个是手掌的,暂不考虑
if (inSlot->getToolType() == AMOTION_EVENT_TOOL_TYPE_PALM) {
std::optional<int32_t> id = getActiveBitId(*inSlot);
if (id) {
outState->rawPointerData.canceledIdBits.markBit(id.value());
}
if (DEBUG_POINTERS) {
ALOGI("Stop processing slot %zu for it received a palm event from device %s",
inIndex, getDeviceName().c_str());
}
continue;
}
// 容错,如果大于最大支持的多点触控,则报错
if (outCount >= MAX_POINTERS) {
if (DEBUG_POINTERS) {
ALOGD("MultiTouch device %s emitted more than maximum of %zu pointers; "
"ignoring the rest.",
getDeviceName().c_str(), MAX_POINTERS);
}
break; // too many fingers!
}
// 将slot转换成RawPointerData
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();
if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
outPointer.toolType = mTouchButtonAccumulator.getToolType();
if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
}
}
// 判断是否支持电容笔,如果支持则返回true,暂时不关心
if (shouldSimulateStylusWithTouch() &&
outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER) {
outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_STYLUS;
}
// 不知道干啥的,估计是鼠标相关的。暂时不管
bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE &&
(mTouchButtonAccumulator.isHovering() ||
(mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
outPointer.isHovering = isHovering;
// Assign pointer id using tracking id if available.
// 这个变量前面直接初始化为true了,所以这里能进去
if (mHavePointerIds) {
// 获取trackingId
int32_t trackingId = inSlot->getTrackingId();
int32_t id = -1;
// 都大于0
if (trackingId >= 0) {
// 这个变量开始应该是空的 !idBits.isEmpty()如果返回true,则for循环就无法进去
for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty();) {
// 找到第一个1,并将它置位成0
uint32_t n = idBits.clearFirstMarkedBit();
if (mPointerTrackingIdMap[n] == trackingId) {
id = n;
}
}
// !mPointerIdBits.isFull()这个函数的意思是如果不包含任何未被标记的位则返回true,开始mPointerIdBits全0,所以进入这个if
if (id < 0 && !mPointerIdBits.isFull()) {
// 将第一个非1的位标记为1,并返回位置,比如说第一次肯定是第0位,id也就等于0,以次类推
id = mPointerIdBits.markFirstUnmarkedBit();
// 将trackingId保存到mPointerTrackingIdMap数组的id位置上
mPointerTrackingIdMap[id] = trackingId;
}
}
// 前面id已经被赋值了,这里就进不去了。
if (id < 0) {
mHavePointerIds = false;
outState->rawPointerData.clearIdBits();
newPointerIdBits.clear();
} else { // 走else
outPointer.id = id; // 这里就代表了mPointerTrackingIdMap的下标
outState->rawPointerData.idToIndex[id] = outCount; // 表示它保存在这个数组中的下标
outState->rawPointerData.markIdBit(id, isHovering);
newPointerIdBits.markBit(id); // 这里将newPointerIdBits的第id位mark成1
}
}
outCount += 1;
}
outState->rawPointerData.pointerCount = outCount;
mPointerIdBits = newPointerIdBits;
mMultiTouchMotionAccumulator.finishSync();
}
到此为止,已经将slot保存为RawState了
void TouchInputMapper::sync(nsecs_t when, nsecs_t readTime) {
// 在末尾插入一个RawState
mRawStatesPending.emplace_back();
// 然后取出来最后一个,就是上面插入的。
RawState& next = mRawStatesPending.back();
// 清理
next.clear();
// 赋值时间
next.when = when;
next.readTime = readTime;
// ... 省略暂时不分析的。
// Sync touch
syncTouch(when, &next);
// The last RawState is the actually second to last, since we just added a new state
// rebegin()获取一个反向的迭代器,这里的index是1,所以是获取的倒数第二个.
const RawState& last =
mRawStatesPending.size() == 1 ? mCurrentRawState : mRawStatesPending.rbegin()[1];
// ... 省略不执行的。
// 开始处理Raw
processRawTouches(false /*timeout*/);
}
继续分析
void TouchInputMapper::processRawTouches(bool timeout) {
// 是否关闭了,一般不会出现这个
if (mDeviceMode == DeviceMode::DISABLED) {
// Drop all input if the device is disabled.
cancelTouch(mCurrentRawState.when, mCurrentRawState.readTime);
mCurrentCookedState.clear();
updateTouchSpots();
return;
}
// Drain any pending touch states. The invariant here is that the mCurrentRawState is always
// valid and must go through the full cook and dispatch cycle. This ensures that anything
// touching the current state will only observe the events that have been dispatched to the
// rest of the pipeline.
// 获取RawState的数量
const size_t N = mRawStatesPending.size();
size_t count;
// 遍历所有的RawState
for (count = 0; count < N; count++) {
const RawState& next = mRawStatesPending[count];
// A failure to assign the stylus id means that we're waiting on stylus data
// and so should defer the rest of the pipeline.
if (assignExternalStylusId(next, timeout)) {
break;
}
// 将next的值拷贝到mCurrentRawState
mCurrentRawState.copyFrom(next);
if (mCurrentRawState.when < mLastRawState.when) {
mCurrentRawState.when = mLastRawState.when;
mCurrentRawState.readTime = mLastRawState.readTime;
}
// 加工事件和分发事件
cookAndDispatch(mCurrentRawState.when, mCurrentRawState.readTime);
}
// ... 暂时省略
}
// 对原始数据进行加工和分发
void TouchInputMapper::cookAndDispatch(nsecs_t when, nsecs_t readTime) {
// Always start with a clean state.
// 这个对象就是保存加工过的事件的,在开始加工之前先清理
mCurrentCookedState.clear();
// Apply stylus buttons to current raw state.
applyExternalStylusButtonState(when);
// Handle policy on initial down or hover events.
bool initialDown = mLastRawState.rawPointerData.pointerCount == 0 &&
mCurrentRawState.rawPointerData.pointerCount != 0;
uint32_t policyFlags = 0;
// 检测当前是否被按下
bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
// ... 省略非触摸的代码
// 加工pointerdata
cookPointerData();
// ... 省略,先分析cookPointerData()
}
// 代码很多,主要是用于处理缩放,矫正等,最后保存为mCurrentCookedState
void TouchInputMapper::cookPointerData() {
uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;
mCurrentCookedState.cookedPointerData.clear();
mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
mCurrentCookedState.cookedPointerData.hoveringIdBits =
mCurrentRawState.rawPointerData.hoveringIdBits;
mCurrentCookedState.cookedPointerData.touchingIdBits =
mCurrentRawState.rawPointerData.touchingIdBits;
mCurrentCookedState.cookedPointerData.canceledIdBits =
mCurrentRawState.rawPointerData.canceledIdBits;
if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
mCurrentCookedState.buttonState = 0;
} else {
mCurrentCookedState.buttonState = mCurrentRawState.buttonState;
}
// Walk through the the active pointers and map device coordinates onto
// display coordinates and adjust for display orientation.
for (uint32_t i = 0; i < currentPointerCount; i++) {
const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
// Size
float touchMajor, touchMinor, toolMajor, toolMinor, size;
switch (mCalibration.sizeCalibration) {
case Calibration::SizeCalibration::GEOMETRIC:
case Calibration::SizeCalibration::DIAMETER:
case Calibration::SizeCalibration::BOX:
case Calibration::SizeCalibration::AREA:
if (mRawPointerAxes.touchMajor.valid && mRawPointerAxes.toolMajor.valid) {
touchMajor = in.touchMajor;
touchMinor = mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
toolMajor = in.toolMajor;
toolMinor = mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor)
: in.touchMajor;
} else if (mRawPointerAxes.touchMajor.valid) {
toolMajor = touchMajor = in.touchMajor;
toolMinor = touchMinor =
mRawPointerAxes.touchMinor.valid ? in.touchMinor : in.touchMajor;
size = mRawPointerAxes.touchMinor.valid ? avg(in.touchMajor, in.touchMinor)
: in.touchMajor;
} else if (mRawPointerAxes.toolMajor.valid) {
touchMajor = toolMajor = in.toolMajor;
touchMinor = toolMinor =
mRawPointerAxes.toolMinor.valid ? in.toolMinor : in.toolMajor;
size = mRawPointerAxes.toolMinor.valid ? avg(in.toolMajor, in.toolMinor)
: in.toolMajor;
} else {
ALOG_ASSERT(false,
"No touch or tool axes. "
"Size calibration should have been resolved to NONE.");
touchMajor = 0;
touchMinor = 0;
toolMajor = 0;
toolMinor = 0;
size = 0;
}
if (mCalibration.haveSizeIsSummed && mCalibration.sizeIsSummed) {
uint32_t touchingCount = mCurrentRawState.rawPointerData.touchingIdBits.count();
if (touchingCount > 1) {
touchMajor /= touchingCount;
touchMinor /= touchingCount;
toolMajor /= touchingCount;
toolMinor /= touchingCount;
size /= touchingCount;
}
}
if (mCalibration.sizeCalibration == Calibration::SizeCalibration::GEOMETRIC) {
touchMajor *= mGeometricScale;
touchMinor *= mGeometricScale;
toolMajor *= mGeometricScale;
toolMinor *= mGeometricScale;
} else if (mCalibration.sizeCalibration == Calibration::SizeCalibration::AREA) {
touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
touchMinor = touchMajor;
toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
toolMinor = toolMajor;
} else if (mCalibration.sizeCalibration == Calibration::SizeCalibration::DIAMETER) {
touchMinor = touchMajor;
toolMinor = toolMajor;
}
mCalibration.applySizeScaleAndBias(&touchMajor);
mCalibration.applySizeScaleAndBias(&touchMinor);
mCalibration.applySizeScaleAndBias(&toolMajor);
mCalibration.applySizeScaleAndBias(&toolMinor);
size *= mSizeScale;
break;
default:
touchMajor = 0;
touchMinor = 0;
toolMajor = 0;
toolMinor = 0;
size = 0;
break;
}
// Pressure
float pressure;
switch (mCalibration.pressureCalibration) {
case Calibration::PressureCalibration::PHYSICAL:
case Calibration::PressureCalibration::AMPLITUDE:
pressure = in.pressure * mPressureScale;
break;
default:
pressure = in.isHovering ? 0 : 1;
break;
}
// Tilt and Orientation
float tilt;
float orientation;
if (mHaveTilt) {
float tiltXAngle = (in.tiltX - mTiltXCenter) * mTiltXScale;
float tiltYAngle = (in.tiltY - mTiltYCenter) * mTiltYScale;
orientation = atan2f(-sinf(tiltXAngle), sinf(tiltYAngle));
tilt = acosf(cosf(tiltXAngle) * cosf(tiltYAngle));
} else {
tilt = 0;
switch (mCalibration.orientationCalibration) {
case Calibration::OrientationCalibration::INTERPOLATED:
orientation = in.orientation * mOrientationScale;
break;
case Calibration::OrientationCalibration::VECTOR: {
int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
int32_t c2 = signExtendNybble(in.orientation & 0x0f);
if (c1 != 0 || c2 != 0) {
orientation = atan2f(c1, c2) * 0.5f;
float confidence = hypotf(c1, c2);
float scale = 1.0f + confidence / 16.0f;
touchMajor *= scale;
touchMinor /= scale;
toolMajor *= scale;
toolMinor /= scale;
} else {
orientation = 0;
}
break;
}
default:
orientation = 0;
}
}
// Distance
float distance;
switch (mCalibration.distanceCalibration) {
case Calibration::DistanceCalibration::SCALED:
distance = in.distance * mDistanceScale;
break;
default:
distance = 0;
}
// Coverage
int32_t rawLeft, rawTop, rawRight, rawBottom;
switch (mCalibration.coverageCalibration) {
case Calibration::CoverageCalibration::BOX:
rawLeft = (in.toolMinor & 0xffff0000) >> 16;
rawRight = in.toolMinor & 0x0000ffff;
rawBottom = in.toolMajor & 0x0000ffff;
rawTop = (in.toolMajor & 0xffff0000) >> 16;
break;
default:
rawLeft = rawTop = rawRight = rawBottom = 0;
break;
}
// Adjust X,Y coords for device calibration
// TODO: Adjust coverage coords?
float xTransformed = in.x, yTransformed = in.y;
mAffineTransform.applyTo(xTransformed, yTransformed);
rotateAndScale(xTransformed, yTransformed);
// Adjust X, Y, and coverage coords for input device orientation.
float left, top, right, bottom;
switch (mInputDeviceOrientation) {
case DISPLAY_ORIENTATION_90:
left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale;
right = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale;
bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
orientation -= M_PI_2;
if (mOrientedRanges.haveOrientation &&
orientation < mOrientedRanges.orientation.min) {
orientation +=
(mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
}
break;
case DISPLAY_ORIENTATION_180:
left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
orientation -= M_PI;
if (mOrientedRanges.haveOrientation &&
orientation < mOrientedRanges.orientation.min) {
orientation +=
(mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
}
break;
case DISPLAY_ORIENTATION_270:
left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale;
top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale;
orientation += M_PI_2;
if (mOrientedRanges.haveOrientation &&
orientation > mOrientedRanges.orientation.max) {
orientation -=
(mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
}
break;
default:
left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale;
right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale;
bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale;
top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale;
break;
}
// Write output coords.
PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
out.clear();
out.setAxisValue(AMOTION_EVENT_AXIS_X, xTransformed);
out.setAxisValue(AMOTION_EVENT_AXIS_Y, yTransformed);
out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
if (mCalibration.coverageCalibration == Calibration::CoverageCalibration::BOX) {
out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
} else {
out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
}
// Write output relative fields if applicable.
uint32_t id = in.id;
if (mSource == AINPUT_SOURCE_TOUCHPAD &&
mLastCookedState.cookedPointerData.hasPointerCoordsForId(id)) {
const PointerCoords& p = mLastCookedState.cookedPointerData.pointerCoordsForId(id);
float dx = xTransformed - p.getAxisValue(AMOTION_EVENT_AXIS_X);
float dy = yTransformed - p.getAxisValue(AMOTION_EVENT_AXIS_Y);
out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, dx);
out.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, dy);
}
// Write output properties.
PointerProperties& properties = mCurrentCookedState.cookedPointerData.pointerProperties[i];
properties.clear();
properties.id = id;
properties.toolType = in.toolType;
// Write id index and mark id as valid.
mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
mCurrentCookedState.cookedPointerData.validIdBits.markBit(id);
}
}
void TouchInputMapper::cookAndDispatch(nsecs_t when, nsecs_t readTime) {
// Always start with a clean state.
// 这个对象就是保存加工过的事件的,在开始加工之前先清理
mCurrentCookedState.clear();
// Apply stylus buttons to current raw state.
applyExternalStylusButtonState(when);
// Handle policy on initial down or hover events.
bool initialDown = mLastRawState.rawPointerData.pointerCount == 0 &&
mCurrentRawState.rawPointerData.pointerCount != 0;
uint32_t policyFlags = 0;
// 检测当前是否被按下
bool buttonsPressed = mCurrentRawState.buttonState & ~mLastRawState.buttonState;
// 下面和辅助显示当前坐标相关,暂时不分析
if (initialDown || buttonsPressed) {
// If this is a touch screen, hide the pointer on an initial down.
if (mDeviceMode == DeviceMode::DIRECT) {
getContext()->fadePointer();
}
if (mParameters.wake) {
policyFlags |= POLICY_FLAG_WAKE;
}
}
// ... 省略
// 加工pointerdata
cookPointerData();
// ... 省略
// Dispatch the touches either directly or by translation through a pointer on screen.
if (mDeviceMode == DeviceMode::POINTER) {
// ... 省略
} else {
if (!mCurrentMotionAborted) {
// ... 省略非触摸事件分发
dispatchTouches(when, readTime, policyFlags);
}
// ... 省略,后面分析
}
// touch事件分发的主要函数
void TouchInputMapper::dispatchTouches(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) {
BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
int32_t metaState = getContext()->getGlobalMetaState();
int32_t buttonState = mCurrentCookedState.buttonState;
// 如果,上一次和当前的一样,但是又有事件发生,那说明是move
if (currentIdBits == lastIdBits) {
if (!currentIdBits.isEmpty()) {
// No pointer id changes so this is a move event.
// The listener takes care of batching moves so we don't have to deal with that here.
dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0,
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits, -1,
mOrientedXPrecision, mOrientedYPrecision, mDownTime);
}
} else { // 如果不一样,则判断一下是那些事件发生。
// There may be pointers going up and pointers going down and pointers moving
// all at the same time.
// 1100 0000 0000 0000 0000 0000 0000 0000 last
// 0100 0000 0000 0000 0000 0000 0000 0000 current
// 取反 1011 1111 1111 1111 1111 1111 1111 1111
// 按位于 1100 0000 0000 0000 0000 0000 0000 0000 last
// 1000 0000 0000 0000 0000 0000 0000 0000 可以看到第一位是1,也就找到哪个trackingId是up事件了,其他类似
BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
BitSet32 dispatchedIdBits(lastIdBits.value);
// Update last coordinates of pointers that have moved so that we observe the new
// pointer positions at the same time as other pointers that have just gone up.
bool moveNeeded =
updateMovedPointers(mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex,
mLastCookedState.cookedPointerData.pointerProperties,
mLastCookedState.cookedPointerData.pointerCoords,
mLastCookedState.cookedPointerData.idToIndex, moveIdBits);
if (buttonState != mLastCookedState.buttonState) {
moveNeeded = true;
}
// Dispatch pointer up events.
while (!upIdBits.isEmpty()) {
uint32_t upId = upIdBits.clearFirstMarkedBit();
bool isCanceled = mCurrentCookedState.cookedPointerData.canceledIdBits.hasBit(upId);
if (isCanceled) {
ALOGI("Canceling pointer %d for the palm event was detected.", upId);
}
dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_UP, 0,
isCanceled ? AMOTION_EVENT_FLAG_CANCELED : 0, metaState, buttonState, 0,
mLastCookedState.cookedPointerData.pointerProperties,
mLastCookedState.cookedPointerData.pointerCoords,
mLastCookedState.cookedPointerData.idToIndex, dispatchedIdBits, upId,
mOrientedXPrecision, mOrientedYPrecision, mDownTime);
dispatchedIdBits.clearBit(upId);
mCurrentCookedState.cookedPointerData.canceledIdBits.clearBit(upId);
}
// Dispatch move events if any of the remaining pointers moved from their old locations.
// Although applications receive new locations as part of individual pointer up
// events, they do not generally handle them except when presented in a move event.
if (moveNeeded && !moveIdBits.isEmpty()) {
ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_MOVE, 0, 0,
metaState, buttonState, 0,
mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex, dispatchedIdBits, -1,
mOrientedXPrecision, mOrientedYPrecision, mDownTime);
}
// Dispatch pointer down events using the new pointer locations.
while (!downIdBits.isEmpty()) {
uint32_t downId = downIdBits.clearFirstMarkedBit();
dispatchedIdBits.markBit(downId);
if (dispatchedIdBits.count() == 1) {
// First pointer is going down. Set down time.
mDownTime = when;
}
// 事件分发
dispatchMotion(when, readTime, policyFlags, mSource, AMOTION_EVENT_ACTION_POINTER_DOWN,
0, 0, metaState, buttonState, 0,
mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex, dispatchedIdBits,
downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
}
}
}
// 事件分发的关键方法
void TouchInputMapper::dispatchMotion(nsecs_t when, nsecs_t readTime, 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]);
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) {
// Replace initial down and final up action.
// We can compare the action without masking off the changed pointer index
// because we know the index is 0.
if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
action = AMOTION_EVENT_ACTION_DOWN;
} else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
if ((flags & AMOTION_EVENT_FLAG_CANCELED) != 0) {
action = AMOTION_EVENT_ACTION_CANCEL;
} else {
action = AMOTION_EVENT_ACTION_UP;
}
} else {
// Can't happen.
ALOG_ASSERT(false);
}
}
float xCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
float yCursorPosition = AMOTION_EVENT_INVALID_CURSOR_POSITION;
if (mDeviceMode == DeviceMode::POINTER) {
mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
}
const int32_t displayId = getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE);
const int32_t deviceId = getDeviceId();
std::vector<TouchVideoFrame> frames = getDeviceContext().getVideoFrames();
std::for_each(frames.begin(), frames.end(),
[this](TouchVideoFrame& frame) { frame.rotate(this->mInputDeviceOrientation); });
// 关键参数构建,这个就是可以认为是MotionEent了
NotifyMotionArgs args(getContext()->getNextId(), when, readTime, deviceId, source, displayId,
policyFlags, action, actionButton, flags, metaState, buttonState,
MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties,
pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
downTime, std::move(frames));
// getListener返回的其实是InputDispater的包装类
getListener().notifyMotion(&args);
}
InputListenerInterface& InputReader::ContextImpl::getListener() {
return mReader->mQueuedListener;
}
// 可以看到这个mQueuedListener就是在构建InputReader的时候传进来的,再看调用构造函数的地方
InputReader::InputReader(std::shared_ptr<EventHubInterface> eventHub,
const sp<InputReaderPolicyInterface>& policy,
InputListenerInterface& listener)
: mContext(this),
mEventHub(eventHub),
mPolicy(policy),
mQueuedListener(listener),
mGlobalMetaState(AMETA_NONE),
mLedMetaState(AMETA_NONE),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
refreshConfigurationLocked(0);
updateGlobalMetaStateLocked();
}
// 调用构造函数的地方,第二个参数就是listener
std::unique_ptr<InputReaderInterface> createInputReader(
const sp<InputReaderPolicyInterface>& policy, InputListenerInterface& listener) {
// 同样的,这里也是创建了一个InputReader,并且传入了一个EentHub,和NativeInputManager以及InputDispatcher
return std::make_unique<InputReader>(std::make_unique<EventHub>(), policy, listener);
}
InputManager::InputManager(
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
// 创建一个inputDispatcher
mDispatcher = createInputDispatcher(dispatcherPolicy);
// 这下面又包装了两次,暂时不管
mClassifier = std::make_unique<InputClassifier>(*mDispatcher);
mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);
// 创建一个inputReader,把readerPolicy和inputdispatcher传进去,这里第二个参数传的是dispatcherPolicy的包装类,我们去看包装类的notifyMotion
mReader = createInputReader(readerPolicy, *mBlocker);
}
// 包装类的notifymotion函数,调用了notifyMotionLocked
void UnwantedInteractionBlocker::notifyMotion(const NotifyMotionArgs* args) {
{ // acquire lock
std::scoped_lock lock(mLock);
const std::vector<NotifyMotionArgs> processedArgs =
mPreferStylusOverTouchBlocker.processMotion(*args);
for (const NotifyMotionArgs& loopArgs : processedArgs) {
notifyMotionLocked(&loopArgs);
}
} // release lock
// Call out to the next stage without holding the lock
mQueuedListener.flush();
}
// 最终都调用了mQueuedListener的notifyMotion方法,我们看一下mQueuedListener是啥
void UnwantedInteractionBlocker::notifyMotionLocked(const NotifyMotionArgs* args) {
auto it = mPalmRejectors.find(args->deviceId);
const bool sendToPalmRejector = it != mPalmRejectors.end() && isFromTouchscreen(args->source);
if (!sendToPalmRejector) {
mQueuedListener.notifyMotion(args);
return;
}
std::vector<NotifyMotionArgs> processedArgs = it->second.processMotion(*args);
for (const NotifyMotionArgs& loopArgs : processedArgs) {
mQueuedListener.notifyMotion(&loopArgs);
}
}
UnwantedInteractionBlocker::UnwantedInteractionBlocker(InputListenerInterface& listener)
: UnwantedInteractionBlocker(listener, isPalmRejectionEnabled()){};
UnwantedInteractionBlocker::UnwantedInteractionBlocker(InputListenerInterface& listener,
bool enablePalmRejection)
: mQueuedListener(listener), mEnablePalmRejection(enablePalmRejection) {}
// 是构造函数,再去看构造调用,UnwantedInteractionBlocker的构造函数传的是mClassifier,那就是说实际上调用了mClassifier的notify,继续看
mDispatcher = createInputDispatcher(dispatcherPolicy);
mClassifier = std::make_unique<InputClassifier>(*mDispatcher);
mBlocker = std::make_unique<UnwantedInteractionBlocker>(*mClassifier);
// mClassifier的构造方法其实就是mDispatcher
InputClassifier::InputClassifier(InputListenerInterface& listener) : mQueuedListener(listener) {}
// 接着看InputClassifier的notify,到这就明白了,一层调一层,最后调到InputDispatcher
void InputClassifier::notifyMotion(const NotifyMotionArgs* args) {
{ // acquire lock
std::scoped_lock lock(mLock);
// MotionClassifier is only used for touch events, for now
const bool sendToMotionClassifier = mMotionClassifier && isTouchEvent(*args);
if (!sendToMotionClassifier) {
mQueuedListener.notifyMotion(args);
} else {
NotifyMotionArgs newArgs(*args);
newArgs.classification = mMotionClassifier->classify(newArgs);
mQueuedListener.notifyMotion(&newArgs);
}
} // release lock
mQueuedListener.flush();
}
// 我们在看flush
void QueuedInputListener::flush() {
for (const std::unique_ptr<NotifyArgs>& args : mArgsQueue) {
args->notify(mInnerListener);
}
mArgsQueue.clear();
}
void NotifyPointerCaptureChangedArgs::notify(InputListenerInterface& listener) const {
listener.notifyPointerCaptureChanged(this);
}
// 也就是说,flush调用之后会回调到设置的listener的notifyPointerCaptureChanged
// 不用看代码我们也可以猜到,应该是InputDispatcher的notifyPointerCaptureChanged
// 去看看,果然有,这里就不分析了,后面在分析InputDispatcher的时候再分析
void InputDispatcher::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
if (DEBUG_INBOUND_EVENT_DETAILS) {
ALOGD("notifyConfigurationChanged - eventTime=%" PRId64, args->eventTime);
}
bool needWake = false;
{ // acquire lock
std::scoped_lock _l(mLock);
std::unique_ptr<ConfigurationChangedEntry> newEntry =
std::make_unique<ConfigurationChangedEntry>(args->id, args->eventTime);
needWake = enqueueInboundEventLocked(std::move(newEntry));
} // release lock
if (needWake) {
mLooper->wake();
}
}
到此为止,InputReader分析完成了