Android input系统原理二

1.inputmanager启动源码分析

在SystemServer.java中构造了 inputmanagerservice的对象,在其构造函数中,最重要的是这个nativeInit函数。 下面是核心代码

java 复制代码
inputManager = new InputManagerService(context);

public InputManagerService(Context context) {
.........
    mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
.........
    LocalServices.addService(InputManagerInternal.class, new LocalService());
}

nativeinit函数

对应的jni函数文件名:com_android_server_input_InputManagerService.cpp

nativeInit 构造了一个NativeInputManager,核心代码中构造了一个EventHub和一个InputManager,并且将EventHub传递给了InputManager。那么InputManager就持有了EventHub类。后续可以看到这个EventHub是读取驱动节点数据的核心类。有用到epoll来监听节点

cpp 复制代码
EventHub::EventHub(void) :
    mEpollFd = epoll_create(EPOLL_SIZE_HINT);

}

在InputManager的构造函数中可以看到接收了InputReaderPolicyInterface 和 InputDispatcherPolicyInterface 虚基类的两个子类对象,因为外部传入的两个this,说明NativeInputManager是继承了这两个虚基类的,这里就不放代码了。

cpp 复制代码
NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
...........

    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);
}


InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}

然后去创建了继承了线程的对象

cpp 复制代码
void InputManager::initialize() {
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}

线程的启动是在nativeStart,最后走到InputManager.cpp中的start函数启动线程

cpp 复制代码
status_t InputManager::start() {
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }

    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);
    if (result) {
        ALOGE("Could not start InputReader thread due to error %d.", result);

        mDispatcherThread->requestExit();
        return result;
    }

    return OK;
}

2.inputReader源码

启动后调用到InputReader.cpp的loopOnce,

cpp 复制代码
void InputReader::loopOnce() {
.........
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
.........
}

在InputReader.h中可以看到mEventBuffer的声明和定义,相当于给getEvents传递了一个长度为256 类型为RawEvent的数组
// The event queue.
static const int EVENT_BUFFER_SIZE = 256;
RawEvent mEventBuffer[EVENT_BUFFER_SIZE];

在EventHub.h可以看到RawEvent的声明,结构体中的这些变量和getevent命令看到的数据非常类似。
/*
 * A raw event as retrieved from the EventHub.
 */
struct RawEvent {
    nsecs_t when;
    int32_t deviceId;
    int32_t type;
    int32_t code;
    int32_t value;
};

在getEvents 函数中,代码量过大,因此贴核心代码

cpp 复制代码
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {

    struct input_event readBuffer[bufferSize];//创建了input_event 的数组,结构体中的数据和RawEvent实际上大差不差
    RawEvent* event = buffer;//event 指向数组头
    size_t capacity = bufferSize;
    bool awoken = false;

    for (;;) {

        if (mNeedToScanDevices) {//默认第一次进来需要扫描设备
            mNeedToScanDevices = false;
            scanDevicesLocked();
            mNeedToSendFinishedDeviceScan = true;
        }
.........
//看后面代码继续分析
}

scanDevicesLocked函数的详细解释

cpp 复制代码
static const char *DEVICE_PATH = "/dev/input";

void EventHub::scanDevicesLocked() {
    status_t res = scanDirLocked(DEVICE_PATH);
    if(res < 0) {
        ALOGE("scan dir failed for %s\n", DEVICE_PATH);
    }
    if (mDevices.indexOfKey(VIRTUAL_KEYBOARD_ID) < 0) {
        createVirtualKeyboardLocked();
    }
}

//打开文件夹/dev/input,读取文件夹下面所有节点,然后在分别打开对应的文件openDeviceLocked
//有了这些信息之后,可以通过这些信息去创建Device对象, 对对应设备加载配置文件或者配置属性
status_t EventHub::scanDirLocked(const char *dirname)
{
    char devname[PATH_MAX];
    char *filename;
    DIR *dir;
    struct dirent *de;
    dir = opendir(dirname);
    if(dir == NULL)
        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);
    }
    closedir(dir);
    return 0;
}


//这个函数很长,核心就是通过ioctl获取一些device 的信息,
status_t EventHub::openDeviceLocked(const char *devicePath) {
    // Get device driver version.
    int driverVersion;
    if(ioctl(fd, EVIOCGVERSION, &driverVersion)) {
        ALOGE("could not get driver version for %s, %s\n", devicePath, strerror(errno));
        close(fd);
        return -1;
    }

    // Get device identifier.
    struct input_id inputId;
    if(ioctl(fd, EVIOCGID, &inputId)) {
        ALOGE("could not get device input id for %s, %s\n", devicePath, strerror(errno));
        close(fd);
        return -1;
    }


    // Allocate device.  (The device object takes ownership of the fd at this point.)
    int32_t deviceId = mNextDeviceId++;
    Device* device = new Device(fd, deviceId, String8(devicePath), identifier);

    // Load the configuration file for the device.
    loadConfigurationLocked(device);//加载配置文件



    // See if this is a touch pad.//对触摸屏配置属性  判断是不是多指触摸
    // Is this a new modern multi-touch driver?
    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;
        }
    // Is this an old style single-touch driver?
    } else if (test_bit(BTN_TOUCH, device->keyBitmask)
            && test_bit(ABS_X, device->absBitmask)
            && test_bit(ABS_Y, device->absBitmask)) {
        device->classes |= INPUT_DEVICE_CLASS_TOUCH;
    // Is this a BT stylus?
    } else if ((test_bit(ABS_PRESSURE, device->absBitmask) ||
                test_bit(BTN_TOUCH, device->keyBitmask))
            && !test_bit(ABS_X, device->absBitmask)
            && !test_bit(ABS_Y, device->absBitmask)) {
        device->classes |= INPUT_DEVICE_CLASS_EXTERNAL_STYLUS;
        // Keyboard will try to claim some of the buttons but we really want to reserve those so we
        // can fuse it with the touch screen data, so just take them back. Note this means an
        // external stylus cannot also be a keyboard device.
        device->classes &= ~INPUT_DEVICE_CLASS_KEYBOARD;
    }

    // Load the key map.//加载按键的配置文件
    // We need to do this for joysticks too because the key layout may specify axes.
    status_t keyMapStatus = NAME_NOT_FOUND;
    if (device->classes & (INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_JOYSTICK)) {
        // Load the keymap for the device.
        keyMapStatus = loadKeyMapLocked(device);
    }


    if (registerDeviceForEpollLocked(device) != OK) {
        delete device;
        return -1;
    }

    configureFd(device);
    addDeviceLocked(device);添加device  将所有扫描到的device通过头插的方式用链表链接起来


}

注册监听fd
status_t EventHub::registerDeviceForEpollLocked(Device* device) {
    struct epoll_event eventItem;
    memset(&eventItem, 0, sizeof(eventItem));
    eventItem.events = EPOLLIN;
    if (mUsingEpollWakeup) {
        eventItem.events |= EPOLLWAKEUP;
    }
    eventItem.data.u32 = device->id;
    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, device->fd, &eventItem)) {
        ALOGE("Could not add device fd to epoll instance.  errno=%d", errno);
        return -errno;
    }
    return OK;
}


//这一段检查输入设备是否为键盘(INPUT_DEVICE_CLASS_KEYBOARD),然后通过 ioctl 调用 EVIOCSREP //来禁用内核的键盘按键重复功能,因为用户态代码会自己处理按键重复逻辑

void EventHub::configureFd(Device* device) {
    // Set fd parameters with ioctl, such as key repeat, suspend block, and clock type
    if (device->classes & INPUT_DEVICE_CLASS_KEYBOARD) {
        // Disable kernel key repeat since we handle it ourselves
        unsigned int repeatRate[] = {0, 0};
        if (ioctl(device->fd, EVIOCSREP, repeatRate)) {
            ALOGW("Unable to disable kernel key repeat for %s: %s",
                  device->path.string(), strerror(errno));
        }
    }

    String8 wakeMechanism("EPOLLWAKEUP");
//这里是为设备配置挂起阻止机制。当 mUsingEpollWakeup 未被启用时,它会尝试通过 ioctl 调用 //EVIOCSSUSPENDBLOCK 来阻止设备进入挂起状态。这个机制用于保证当设备处于挂起状态时,仍然能够唤醒//系统处理输入事件
    if (!mUsingEpollWakeup) {
#ifndef EVIOCSSUSPENDBLOCK
        // uapi headers don't include EVIOCSSUSPENDBLOCK, and future kernels
        // will use an epoll flag instead, so as long as we want to support
        // this feature, we need to be prepared to define the ioctl ourselves.
#define EVIOCSSUSPENDBLOCK _IOW('E', 0x91, int)
#endif
        if (ioctl(device->fd, EVIOCSSUSPENDBLOCK, 1)) {
            wakeMechanism = "<none>";
        } else {
            wakeMechanism = "EVIOCSSUSPENDBLOCK";
        }
    }
//设置输入设备使用单调时钟(CLOCK_MONOTONIC)来记录事件的时间戳。单调时钟保证时间总是向前移动,//避免系统时钟调整(如夏令时变化)对输入事件的时间戳产生影响
    // Tell the kernel that we want to use the monotonic clock for reporting timestamps
    // associated with input events.  This is important because the input system
    // uses the timestamps extensively and assumes they were recorded using the monotonic
    // clock.
    int clockId = CLOCK_MONOTONIC;
    bool usingClockIoctl = !ioctl(device->fd, EVIOCSCLOCKID, &clockId);
    ALOGI("wakeMechanism=%s, usingClockIoctl=%s", wakeMechanism.string(),
          toString(usingClockIoctl));
}


void EventHub::addDeviceLocked(Device* device) {
    mDevices.add(device->id, device);
    device->next = mOpeningDevices;
    mOpeningDevices = device;
}

scanDevicesLocked 总结就是扫描监听文件,通过ioctl去驱动中获取不同设备的信息,不同输入设陪配置流程不同,加载配置文件,创建Device,最后将Device存起来。

cpp 复制代码
//这段代码就是将刚才形成链表的device分别遍历将id取出来,赋值给event存起来。
while (mOpeningDevices != NULL) {
    Device* device = mOpeningDevices;
    ALOGV("Reporting device opened: id=%d, name=%s\n",
            device->id, device->path.string());
    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;
    }
}
//这里为true,如果有5个device的话,这里在添加一个,那么就总共有6个了。
if (mNeedToSendFinishedDeviceScan) {
    mNeedToSendFinishedDeviceScan = false;
    event->when = now;
    event->type = FINISHED_DEVICE_SCAN;
    event += 1;
    if (--capacity == 0) {
        break;
    }
}

接下来就会执行这里,因为第一次扫描设备,其它代码都不会执行

cpp 复制代码
// Return now if we have collected any events or if we were explicitly awoken.
if (event != buffer || awoken) {
    break;
}

//break之后,返回扫描到的设备数
// All done, return the number of events we read.
return event - buffer;

在InputReader.cpp中,在getEvents函数之后会返回设备数,如果扫描到了5个设备,那么这里会返回6,具体可以看上面getEvents的函数源码解析

cpp 复制代码
void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
..........
    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);

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

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

        if (mNextTimeout != LLONG_MAX) {
            nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
            if (now >= mNextTimeout) {
#if DEBUG_RAW_EVENTS
                ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
#endif
                mNextTimeout = LLONG_MAX;
                timeoutExpiredLocked(now);
            }
        }

        if (oldGeneration != mGeneration) {
            inputDevicesChanged = true;
            getInputDevicesLocked(inputDevices);
        }
    } // release lock

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

    // Flush queued events out to the listener.
    // This must happen outside of the lock because the listener could potentially call
    // back into the InputReader's methods, such as getScanCodeState, or become blocked
    // on another thread similarly waiting to acquire the InputReader lock thereby
    // resulting in a deadlock.  This situation is actually quite plausible because the
    // listener is actually the input dispatcher, which calls into the window manager,
    // which occasionally calls into the input reader.
    mQueuedListener->flush();
}

就下来会进入到processEventsLocked对device进行处理,很明显,根据device type,这里将会进入addDeviceLocked

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) {
            int32_t deviceId = rawEvent->deviceId;
            while (batchSize < count) {
                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
                        || rawEvent[batchSize].deviceId != deviceId) {
                    break;
                }
                batchSize += 1;
            }
#if DEBUG_RAW_EVENTS
            ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
#endif
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        } else {
            switch (rawEvent->type) {
            case EventHubInterface::DEVICE_ADDED:
                addDeviceLocked(rawEvent->when, rawEvent->deviceId);
                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;
    }
}

void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
//这里验证deviceId是否在mDevices中存在,如果存在,就不需要再添加一遍了
    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
    if (deviceIndex >= 0) {
        ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
        return;
    }
    //根据deviceId去获取device的相关信息
    InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
    uint32_t classes = mEventHub->getDeviceClasses(deviceId);
    int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
    //创建InputDevice
    InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
    device->configure(when, &mConfig, 0);
    device->reset(when);

    if (device->isIgnored()) {
        ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
                identifier.name.string());
    } else {
        ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId,
                identifier.name.string(), device->getSources());
    }

    //将InputDevice放入到mDevices存起来
    mDevices.add(deviceId, device);
    bumpGenerationLocked();

    if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
        notifyExternalStylusPresenceChanged();
    }
}

//这里是给每个InputDevice都添加了一个Mapper,由Mapper将原始数据转换为真正的触摸数据
InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
        const InputDeviceIdentifier& identifier, uint32_t classes) {
    InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
            controllerNumber, identifier, classes);

    // External devices.
    if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
        device->setExternal(true);
    }

    // Devices with mics.
    if (classes & INPUT_DEVICE_CLASS_MIC) {
        device->setMic(true);
    }

    // Switch-like devices.
    if (classes & INPUT_DEVICE_CLASS_SWITCH) {
        device->addMapper(new SwitchInputMapper(device));
    }

    // Scroll wheel-like devices.
    if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
        device->addMapper(new RotaryEncoderInputMapper(device));
    }

    // Vibrator-like devices.
    if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
        device->addMapper(new VibratorInputMapper(device));
    }

    // Keyboard-like devices.
    uint32_t keyboardSource = 0;
    int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
    if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
        keyboardSource |= AINPUT_SOURCE_KEYBOARD;
    }
    if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
        keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
    }
    if (classes & INPUT_DEVICE_CLASS_DPAD) {
        keyboardSource |= AINPUT_SOURCE_DPAD;
    }
    if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
        keyboardSource |= AINPUT_SOURCE_GAMEPAD;
    }

    if (keyboardSource != 0) {
        device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
    }

    // Cursor-like devices.
    if (classes & INPUT_DEVICE_CLASS_CURSOR) {
        device->addMapper(new CursorInputMapper(device));
    }

    // Touchscreens and touchpad devices.
    if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
        device->addMapper(new MultiTouchInputMapper(device));
    } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
        device->addMapper(new SingleTouchInputMapper(device));
    }

    // Joystick-like devices.
    if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
        device->addMapper(new JoystickInputMapper(device));
    }

    // External stylus-like devices.
    if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
        device->addMapper(new ExternalStylusInputMapper(device));
    }

    return device;
}

在processEventsLocked中,会循环处理每个device。

然后循环第二次进入getevent,前面的流程都不会执行,在这里会等待事件的发生,如果有事件发生,那么mPendingEventItems中将会存储eventItem

cpp 复制代码
mPendingEventIndex = 0;

release_wake_lock(WAKE_LOCK_ID);

int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);

如果有事件发生,那么mPendingEventIndex将会为0,mPendingEventCount至少也是1.就会进入这个while循环中。

cpp 复制代码
while (mPendingEventIndex < mPendingEventCount) {
    const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
    //判断是否有新的节点添加或删除
    if (eventItem.data.u32 == EPOLL_ID_INOTIFY) {
        if (eventItem.events & EPOLLIN) {
            mPendingINotify = true;
        } else {
            ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
        }
        continue;
    }

........

    //获取对应device,通过device来读取event,最多读取256个inputevent
    ssize_t deviceIndex = mDevices.indexOfKey(eventItem.data.u32);
    if (deviceIndex < 0) {
        ALOGW("Received unexpected epoll event 0x%08x for unknown device id %d.",
                eventItem.events, eventItem.data.u32);
        continue;
    }

    Device* device = mDevices.valueAt(deviceIndex);
    if (eventItem.events & EPOLLIN) {
        int32_t readSize = read(device->fd, readBuffer,
                sizeof(struct input_event) * capacity);
    if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
..........
    } else if (readSize < 0) {
..........
    } else if ((readSize % sizeof(struct input_event)) != 0) {
..........
    } else {
        int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
        //计算读取到了多少个input_event
        size_t count = size_t(readSize) / sizeof(struct input_event);
        for (size_t i = 0; i < count; i++) {
            struct input_event& iev = readBuffer[i];
            ALOGV("%s got: time=%d.%06d, type=%d, code=%d, value=%d",
                    device->path.string(),
                    (int) iev.time.tv_sec, (int) iev.time.tv_usec,
                    iev.type, iev.code, iev.value);

            // Some input devices may have a better concept of the time
            // when an input event was actually generated than the kernel
            // which simply timestamps all events on entry to evdev.
            // This is a custom Android extension of the input protocol
            // mainly intended for use with uinput based device drivers.
            if (iev.type == EV_MSC) {
                if (iev.code == MSC_ANDROID_TIME_SEC) {
                    device->timestampOverrideSec = iev.value;
                    continue;
                } else if (iev.code == MSC_ANDROID_TIME_USEC) {
                    device->timestampOverrideUsec = iev.value;
                    continue;
                }
            }
            if (device->timestampOverrideSec || device->timestampOverrideUsec) {
                iev.time.tv_sec = device->timestampOverrideSec;
                iev.time.tv_usec = device->timestampOverrideUsec;
                if (iev.type == EV_SYN && iev.code == SYN_REPORT) {
                    device->timestampOverrideSec = 0;
                    device->timestampOverrideUsec = 0;
                }
                ALOGV("applied override time %d.%06d",
                        int(iev.time.tv_sec), int(iev.time.tv_usec));
            }

            // Use the time specified in the event instead of the current time
            // so that downstream code can get more accurate estimates of
            // event dispatch latency from the time the event is enqueued onto
            // the evdev client buffer.
            //
            // The event's timestamp fortuitously uses the same monotonic clock
            // time base as the rest of Android.  The kernel event device driver
            // (drivers/input/evdev.c) obtains timestamps using ktime_get_ts().
            // The systemTime(SYSTEM_TIME_MONOTONIC) function we use everywhere
            // calls clock_gettime(CLOCK_MONOTONIC) which is implemented as a
            // system call that also queries ktime_get_ts().
            event->when = nsecs_t(iev.time.tv_sec) * 1000000000LL
                    + nsecs_t(iev.time.tv_usec) * 1000LL;
            ALOGV("event time %" PRId64 ", now %" PRId64, event->when, now);

            // Bug 7291243: Add a guard in case the kernel generates timestamps
            // that appear to be far into the future because they were generated
            // using the wrong clock source.
            //
            // This can happen because when the input device is initially opened
            // it has a default clock source of CLOCK_REALTIME.  Any input events
            // enqueued right after the device is opened will have timestamps
            // generated using CLOCK_REALTIME.  We later set the clock source
            // to CLOCK_MONOTONIC but it is already too late.
            //
            // Invalid input event timestamps can result in ANRs, crashes and
            // and other issues that are hard to track down.  We must not let them
            // propagate through the system.
            //
            // Log a warning so that we notice the problem and recover gracefully.
            if (event->when >= now + 10 * 1000000000LL) {
                // Double-check.  Time may have moved on.
                nsecs_t time = systemTime(SYSTEM_TIME_MONOTONIC);
                if (event->when > time) {
                    ALOGW("An input event from %s has a timestamp that appears to "
                            "have been generated using the wrong clock source "
                            "(expected CLOCK_MONOTONIC): "
                            "event time %" PRId64 ", current time %" PRId64
                            ", call time %" PRId64 ".  "
                            "Using current time instead.",
                            device->path.string(), event->when, time, now);
                    event->when = time;
                } else {
                    ALOGV("Event time is ok but failed the fast path and required "
                            "an extra call to systemTime: "
                            "event time %" PRId64 ", current time %" PRId64
                            ", call time %" PRId64 ".",
                            event->when, time, now);
                }
            }
            //在将inputevent转化为RawEvent
            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;
        }
    }

}

到这里又因为event != buffer退出循环了,后续去处理RawEvent
// Return now if we have collected any events or if we were explicitly awoken.
if (event != buffer || awoken) {
    break;
}

调用processEventsLocked对数据进行处理,这里本质上是找出同一个设备产生的一些了device进行处理

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;
        //使用这个逻辑对具体时间进行处理
        //1.如果某个设备产生了10个数据,预期是把这10个数据同时处理掉,但是如果这10个数据之间
        //有其它设备产生的数据,那么就会退出下面这个while循环。先处理同一个设备产生的数据。
        if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
            int32_t deviceId = rawEvent->deviceId;
            while (batchSize < count) {
                if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
                        || rawEvent[batchSize].deviceId != deviceId) {
                    break;
                }
                batchSize += 1;
            }
#if DEBUG_RAW_EVENTS
            ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
#endif
            //在这里处理由同一个device产生的一连串的数据
            processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
        } else {
....
....
        }
        count -= batchSize;
        rawEvent += batchSize;
    }
}

processEventsForDeviceLocked中找出id对应的InputDevice调用process进行处理

cpp 复制代码
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
        const RawEvent* rawEvents, size_t count) {
    ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
    if (deviceIndex < 0) {
        ALOGW("Discarding event for unknown deviceId %d.", deviceId);
        return;
    }

    InputDevice* device = mDevices.valueAt(deviceIndex);
    if (device->isIgnored()) {
        //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
        return;
    }

    device->process(rawEvents, count);
}

在InputDevice::process函数中,默认mDropUntilNextSync为false,所以调用mapper->process进行处理

cpp 复制代码
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    // Process all of the events in order for each mapper.
    // We cannot simply ask each mapper to process them in bulk because mappers may
    // have side-effects that must be interleaved.  For example, joystick movement events and
    // gamepad button presses are handled by different mappers but they should be dispatched
    // in the order received.
    size_t numMappers = mMappers.size();
    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);
#endif

        if (mDropUntilNextSync) {
            if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
                mDropUntilNextSync = false;
#if DEBUG_RAW_EVENTS
                ALOGD("Recovered from input event buffer overrun.");
#endif
            } else {
#if DEBUG_RAW_EVENTS
                ALOGD("Dropped input event while waiting for next input sync.");
#endif
            }
        } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
            //是一种异常情况,不具体分析
            ALOGI("Detected input event buffer overrun for device %s.", getName().string());
            mDropUntilNextSync = true;
            reset(rawEvent->when);
        } else {
            for (size_t i = 0; i < numMappers; i++) {
                InputMapper* mapper = mMappers[i];
                mapper->process(rawEvent);
            }
        }
        --count;
    }
}

如果设备是触摸屏,那么会调用MultiTouchInputMapper的process进行处理,对照数据进行分析

cpp 复制代码
void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
    TouchInputMapper::process(rawEvent);

    mMultiTouchMotionAccumulator.process(rawEvent);
}

void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
    if (rawEvent->type == EV_ABS) {
        //最开始数据是ABS类型
        bool newSlot = false;
        //是不是用的slot协议,一般都是这种协议
        if (mUsingSlotsProtocol) {
            //code最开始是ABS_MT_SLOT
            if (rawEvent->code == ABS_MT_SLOT) {
                //将触点id保存
                mCurrentSlot = rawEvent->value;
                //表示有新的slot
                newSlot = true;
            }
        } else if (mCurrentSlot < 0) {
            mCurrentSlot = 0;
        }
        
        //mCurrentSlot 到这里不会小于0,触点大于等于16时将会报错不支持。  第一次slot判断到此结束
        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);
            }
#endif
        } else {
            //当mCurrentSlot为0时
            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;
            //abs 数据第二次处理,value不为0,表示触点没松开,触点松开时value为1

            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) {
        // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
        mCurrentSlot += 1;
    } else if (rawEvent->type == EV_MSC && rawEvent->code == MSC_TIMESTAMP) {
        mDeviceTimestamp = rawEvent->value;
    }
}



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);
    }
}


void TouchInputMapper::sync(nsecs_t when) {
    const RawState* last = mRawStatesPending.isEmpty() ?
            &mCurrentRawState : &mRawStatesPending.top();

    // Push a new state.
    mRawStatesPending.push();
    RawState* next = &mRawStatesPending.editTop();
    next->clear();
    next->when = when;

    // Sync button state.
    next->buttonState = mTouchButtonAccumulator.getButtonState()
            | mCursorButtonAccumulator.getButtonState();

    // Sync scroll
    next->rawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
    next->rawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
    mCursorScrollAccumulator.finishSync();

    // Sync touch
    syncTouch(when, next);

    // Assign pointer ids.
    if (!mHavePointerIds) {
        assignPointerIds(last, next);
    }

#if DEBUG_RAW_EVENTS
    ALOGD("syncTouch: pointerCount %d -> %d, touching ids 0x%08x -> 0x%08x, "
            "hovering ids 0x%08x -> 0x%08x",
            last->rawPointerData.pointerCount,
            next->rawPointerData.pointerCount,
            last->rawPointerData.touchingIdBits.value,
            next->rawPointerData.touchingIdBits.value,
            last->rawPointerData.hoveringIdBits.value,
            next->rawPointerData.hoveringIdBits.value);
#endif

    processRawTouches(false /*timeout*/);
}


void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
    //获取slotcount  值为16
    size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
    size_t outCount = 0;
    BitSet32 newPointerIdBits;
    mHavePointerIds = true;
    //这里遍历每个slot  判断触点是不是还在,如果触点不在,直接略过
    for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
        const MultiTouchMotionAccumulator::Slot* inSlot =
                mMultiTouchMotionAccumulator.getSlot(inIndex);
        if (!inSlot->isInUse()) {
            continue;
        }

        if (outCount >= MAX_POINTERS) {
#if DEBUG_POINTERS
            ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
                    "ignoring the rest.",
                    getDeviceName().string(), MAX_POINTERS);
#endif
            break; // too many fingers!
        }

        //构建一个触点对象,数据来自slot
        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;
            }
        }

        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.
        if (mHavePointerIds) {
            int32_t trackingId = inSlot->getTrackingId();
            int32_t id = -1;
            if (trackingId >= 0) {
                for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
                    //查找并清除第一个被标记的位(即值为 1 的位),然后返回该位的索引
                    uint32_t n = idBits.clearFirstMarkedBit();
                    if (mPointerTrackingIdMap[n] == trackingId) {
                        id = n;
                    }
                }
                //第一次在这里id小于0,并且mPointerIdBits没有满
                if (id < 0 && !mPointerIdBits.isFull()) {
                    id = mPointerIdBits.markFirstUnmarkedBit();//第一次这里返回0,标记第一个没有被标记过的下标,并返回索引
                    //保存trackingId
                    mPointerTrackingIdMap[id] = trackingId;
                }
            }
            if (id < 0) {
                mHavePointerIds = false;
                outState->rawPointerData.clearIdBits();
                newPointerIdBits.clear();
            } else {
                //记录id
                outPointer.id = id;
                //第一个触点
                outState->rawPointerData.idToIndex[id] = outCount;
                outState->rawPointerData.markIdBit(id, isHovering);
                newPointerIdBits.markBit(id);
            }
        }
        outCount += 1;
    }

    outState->deviceTimestamp = mMultiTouchMotionAccumulator.getDeviceTimestamp();
    outState->rawPointerData.pointerCount = outCount;
    mPointerIdBits = newPointerIdBits;

    mMultiTouchMotionAccumulator.finishSync();
}


void TouchInputMapper::processRawTouches(bool timeout) {
    //这里判断是不是某个状态抛弃所有触摸数据
    if (mDeviceMode == DEVICE_MODE_DISABLED) {
        // Drop all input if the device is disabled.
        mCurrentRawState.clear();
        mRawStatesPending.clear();
        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.
    const size_t N = mRawStatesPending.size();
    size_t count;
    for(count = 0; count < N; count++) {
        //取出RawState对象的数据,数据在syncTouch时填入
        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;
        }

        // All ready to go.
        clearStylusDataPendingFlags();
        //拷贝一份数据
        mCurrentRawState.copyFrom(next);
        if (mCurrentRawState.when < mLastRawState.when) {
            mCurrentRawState.when = mLastRawState.when;
        }
        //关键方法
        cookAndDispatch(mCurrentRawState.when);
    }
    if (count != 0) {
        mRawStatesPending.removeItemsAt(0, count);
    }

    if (mExternalStylusDataPending) {
        if (timeout) {
            nsecs_t when = mExternalStylusFusionTimeout - STYLUS_DATA_LATENCY;
            clearStylusDataPendingFlags();
            mCurrentRawState.copyFrom(mLastRawState);
#if DEBUG_STYLUS_FUSION
            ALOGD("Timeout expired, synthesizing event with new stylus data");
#endif
            cookAndDispatch(when);
        } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
            mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
            getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
        }
    }
}

分析cookAndDispatch

cpp 复制代码
void TouchInputMapper::cookAndDispatch(nsecs_t when) {
    // 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 == DEVICE_MODE_DIRECT) {
            getContext()->fadePointer();
        }

        if (mParameters.wake) {
            policyFlags |= POLICY_FLAG_WAKE;
        }
    }

    // Consume raw off-screen touches before cooking pointer data.
    // If touches are consumed, subsequent code will not receive any pointer data.
    if (consumeRawTouches(when, policyFlags)) {
        //
        mCurrentRawState.rawPointerData.clear();
    }

    // Cook pointer data.  This call populates the mCurrentCookedState.cookedPointerData structure
    // with cooked pointer data that has the same ids and indices as the raw data.
    // The following code can use either the raw or cooked data, as needed.
    //关键方法
    cookPointerData();

    // Apply stylus pressure to current cooked state.
    applyExternalStylusTouchState(when);

    // Synthesize key down from raw buttons if needed.
    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
            policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState);

    // Dispatch the touches either directly or by translation through a pointer on screen.
    if (mDeviceMode == DEVICE_MODE_POINTER) {
        for (BitSet32 idBits(mCurrentRawState.rawPointerData.touchingIdBits);
                !idBits.isEmpty(); ) {
            uint32_t id = idBits.clearFirstMarkedBit();
            const RawPointerData::Pointer& pointer =
                    mCurrentRawState.rawPointerData.pointerForId(id);
            if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
                    || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
                mCurrentCookedState.stylusIdBits.markBit(id);
            } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_FINGER
                    || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
                mCurrentCookedState.fingerIdBits.markBit(id);
            } else if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_MOUSE) {
                mCurrentCookedState.mouseIdBits.markBit(id);
            }
        }
        for (BitSet32 idBits(mCurrentRawState.rawPointerData.hoveringIdBits);
                !idBits.isEmpty(); ) {
            uint32_t id = idBits.clearFirstMarkedBit();
            const RawPointerData::Pointer& pointer =
                    mCurrentRawState.rawPointerData.pointerForId(id);
            if (pointer.toolType == AMOTION_EVENT_TOOL_TYPE_STYLUS
                    || pointer.toolType == AMOTION_EVENT_TOOL_TYPE_ERASER) {
                mCurrentCookedState.stylusIdBits.markBit(id);
            }
        }

        // Stylus takes precedence over all tools, then mouse, then finger.
        PointerUsage pointerUsage = mPointerUsage;
        if (!mCurrentCookedState.stylusIdBits.isEmpty()) {
            mCurrentCookedState.mouseIdBits.clear();
            mCurrentCookedState.fingerIdBits.clear();
            pointerUsage = POINTER_USAGE_STYLUS;
        } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
            mCurrentCookedState.fingerIdBits.clear();
            pointerUsage = POINTER_USAGE_MOUSE;
        } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
                isPointerDown(mCurrentRawState.buttonState)) {
            pointerUsage = POINTER_USAGE_GESTURES;
        }

        dispatchPointerUsage(when, policyFlags, pointerUsage);
    } else {
        if (mDeviceMode == DEVICE_MODE_DIRECT
                && mConfig.showTouches && mPointerController != NULL) {
            mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
            mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);

            mPointerController->setButtonState(mCurrentRawState.buttonState);
            mPointerController->setSpots(mCurrentCookedState.cookedPointerData.pointerCoords,
                    mCurrentCookedState.cookedPointerData.idToIndex,
                    mCurrentCookedState.cookedPointerData.touchingIdBits);
        }

        if (!mCurrentMotionAborted) {
            dispatchButtonRelease(when, policyFlags);
            dispatchHoverExit(when, policyFlags);
            //触摸点派发
            dispatchTouches(when, policyFlags);
            dispatchHoverEnterAndMove(when, policyFlags);
            dispatchButtonPress(when, policyFlags);
        }

        if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
            mCurrentMotionAborted = false;
        }
    }

    // Synthesize key up from raw buttons if needed.
    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
            policyFlags, mLastCookedState.buttonState, mCurrentCookedState.buttonState);

    // Clear some transient state.
    mCurrentRawState.rawVScroll = 0;
    mCurrentRawState.rawHScroll = 0;

    // Copy current touch to last touch in preparation for the next cycle.
    mLastRawState.copyFrom(mCurrentRawState);
    mLastCookedState.copyFrom(mCurrentCookedState);
}



void TouchInputMapper::cookPointerData() {
    //获取有多少个触点
    uint32_t currentPointerCount = mCurrentRawState.rawPointerData.pointerCount;

    mCurrentCookedState.cookedPointerData.clear();
    mCurrentCookedState.deviceTimestamp =
            mCurrentRawState.deviceTimestamp;
    //按下点的个数
    mCurrentCookedState.cookedPointerData.pointerCount = currentPointerCount;
    mCurrentCookedState.cookedPointerData.hoveringIdBits =
            mCurrentRawState.rawPointerData.hoveringIdBits;
    //按下id的集合
    mCurrentCookedState.cookedPointerData.touchingIdBits =
            mCurrentRawState.rawPointerData.touchingIdBits;
    //判断按下点的个数是否为0,正常不会为0
    if (mCurrentCookedState.cookedPointerData.pointerCount == 0) {
        mCurrentCookedState.buttonState = 0;
    } else {
        mCurrentCookedState.buttonState = mCurrentRawState.buttonState;
    }

    // Walk through the the active pointers and map device coordinates onto
    // surface 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;
        //size的校准  长轴短轴的校准
        switch (mCalibration.sizeCalibration) {
        case Calibration::SIZE_CALIBRATION_GEOMETRIC:
        case Calibration::SIZE_CALIBRATION_DIAMETER:
        case Calibration::SIZE_CALIBRATION_BOX:
        case Calibration::SIZE_CALIBRATION_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::SIZE_CALIBRATION_GEOMETRIC) {
                touchMajor *= mGeometricScale;
                touchMinor *= mGeometricScale;
                toolMajor *= mGeometricScale;
                toolMinor *= mGeometricScale;
            } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_AREA) {
                touchMajor = touchMajor > 0 ? sqrtf(touchMajor) : 0;
                touchMinor = touchMajor;
                toolMajor = toolMajor > 0 ? sqrtf(toolMajor) : 0;
                toolMinor = toolMajor;
            } else if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_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::PRESSURE_CALIBRATION_PHYSICAL:
        case Calibration::PRESSURE_CALIBRATION_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::ORIENTATION_CALIBRATION_INTERPOLATED:
                orientation = in.orientation * mOrientationScale;
                break;
            case Calibration::ORIENTATION_CALIBRATION_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::DISTANCE_CALIBRATION_SCALED:
            distance = in.distance * mDistanceScale;
            break;
        default:
            distance = 0;
        }

        // Coverage   覆盖面校准
        int32_t rawLeft, rawTop, rawRight, rawBottom;
        switch (mCalibration.coverageCalibration) {
        case Calibration::COVERAGE_CALIBRATION_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;
        }
        //x y 坐标校准
        // Adjust X,Y coords for device calibration
        // TODO: Adjust coverage coords?
        float xTransformed = in.x, yTransformed = in.y;
        mAffineTransform.applyTo(xTransformed, yTransformed);

        // Adjust X, Y, and coverage coords for surface orientation.
        float x, y;
        float left, top, right, bottom;

        switch (mSurfaceOrientation) {
        case DISPLAY_ORIENTATION_90:
            x = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
            y = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
            left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
            right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
            bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
            top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
            orientation -= M_PI_2;
            if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
                orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
            }
            break;
        case DISPLAY_ORIENTATION_180:
            x = float(mRawPointerAxes.x.maxValue - xTransformed) * mXScale + mXTranslate;
            y = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
            left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
            right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
            bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
            top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
            orientation -= M_PI;
            if (mOrientedRanges.haveOrientation && orientation < mOrientedRanges.orientation.min) {
                orientation += (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
            }
            break;
        case DISPLAY_ORIENTATION_270:
            x = float(mRawPointerAxes.y.maxValue - yTransformed) * mYScale + mYTranslate;
            y = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
            left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
            right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
            bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
            top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
            orientation += M_PI_2;
            if (mOrientedRanges.haveOrientation && orientation > mOrientedRanges.orientation.max) {
                orientation -= (mOrientedRanges.orientation.max - mOrientedRanges.orientation.min);
            }
            break;
        default:
            x = float(xTransformed - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
            y = float(yTransformed - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
            left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
            right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
            bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
            top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
            break;
        }

        // Write output coords.
        PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
        out.clear();
        out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
        out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
        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::COVERAGE_CALIBRATION_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 properties.
        PointerProperties& properties =
                mCurrentCookedState.cookedPointerData.pointerProperties[i];
        uint32_t id = in.id;
        properties.clear();
        properties.id = id;
        properties.toolType = in.toolType;

        // Write id index.
        mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
    }
}



void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
    //触点的个数
    BitSet32 currentIdBits = mCurrentCookedState.cookedPointerData.touchingIdBits;
    //上一次触点
    BitSet32 lastIdBits = mLastCookedState.cookedPointerData.touchingIdBits;
    int32_t metaState = getContext()->getGlobalMetaState();
    int32_t buttonState = mCurrentCookedState.buttonState;
    //本次触点和上一次触点是相等的   没有手指的变化
    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.
            //没有触点的变化并且不为null,还有事件的变化,所以判定为触点的移动
            dispatchMotion(when, policyFlags, mSource,
                    AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
                    AMOTION_EVENT_EDGE_FLAG_NONE,
                    mCurrentCookedState.deviceTimestamp,
                    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.
        //如果有触点的变化,那么判定是否有触点的按下或抬起或者同时有触点的移动
        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.
        //比较last触点坐标的变化来判定是否有触点的移动
        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;
        }
        //是否有up事件
        // Dispatch pointer up events.
        while (!upIdBits.isEmpty()) {
            uint32_t upId = upIdBits.clearFirstMarkedBit();

            dispatchMotion(when, policyFlags, mSource,
                    AMOTION_EVENT_ACTION_POINTER_UP, 0, 0, metaState, buttonState, 0,
                    mCurrentCookedState.deviceTimestamp,
                    mLastCookedState.cookedPointerData.pointerProperties,
                    mLastCookedState.cookedPointerData.pointerCoords,
                    mLastCookedState.cookedPointerData.idToIndex,
                    dispatchedIdBits, upId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
            dispatchedIdBits.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.
        //是否有move事件
        if (moveNeeded && !moveIdBits.isEmpty()) {
            ALOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
            dispatchMotion(when, policyFlags, mSource,
                    AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState, 0,
                    mCurrentCookedState.deviceTimestamp,
                    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, policyFlags, mSource,
                    AMOTION_EVENT_ACTION_POINTER_DOWN, 0, 0, metaState, buttonState, 0,
                    mCurrentCookedState.deviceTimestamp,
                    mCurrentCookedState.cookedPointerData.pointerProperties,
                    mCurrentCookedState.cookedPointerData.pointerCoords,
                    mCurrentCookedState.cookedPointerData.idToIndex,
                    dispatchedIdBits, downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
        }
    }
}
相关推荐
CS Beginner3 分钟前
【搭建】个人博客网站的搭建
java·前端·学习·servlet·log4j·mybatis
JavaTree201739 分钟前
【Spring Boot】Spring Boot解决循环依赖
java·spring boot·后端
lang201509281 小时前
Maven 五分钟入门
java·maven
cj6341181501 小时前
SpringBoot配置Redis
java·后端
用坏多个鼠标1 小时前
Nacos和Nginx集群,项目启动失败问题
java·开发语言
雨白2 小时前
Flow 的异常处理与执行控制
android·kotlin
TangKenny2 小时前
基于EasyExcel的动态列映射读取方案
java·easyexcel
安冬的码畜日常2 小时前
【JUnit实战3_19】第十章:用 Maven 3 运行 JUnit 测试(下)
java·测试工具·junit·单元测试·maven·junit5
lemon_sjdk2 小时前
软件开发模式架构选择
java·架构·软件开发·前后端分离
董广明2 小时前
单元测试(JUnit、Mockito、PowerMock )
java·经验分享·junit·单元测试