frameworks 之InputReader


android 输入事件 主要分 2个流程 事件读取事件分发。本文讲解事件输入流程。
涉及到的类如下
-frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
frameworks/native/services/inputflinger/InputManager.cpp
frameworks/native/services/inputflinger/dispatcher/InputDispatcherFactory.cpp
frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp
frameworks/native/services/inputflinger/reader/EventHub.cpp
frameworks/native/services/inputflinger/reader/InputReader.cpp
frameworks/native/services/inputflinger/InputThread.cpp
frameworks/native/services/inputflinger/reader/include/EventHub.h
frameworks/native/services/inputflinger/reader/InputDevice.cpp
frameworks/native/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
frameworks/native/services/inputflinger/reader/mapper/TouchInputMapper.cpp
system/core/libutils/include/utils/BitSet.h

InputManagerService 初始化

SystemService启动时候,启动了一系列服务包括 InputManagerService 。在 startOtherServices 方法中 ,初始化了该服务。

// frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
	...
	InputManagerService inputManager = null;
	...
	t.traceBegin("StartInputManagerService");
	// 初始化服务
    inputManager = new InputManagerService(context);
    t.traceEnd();
}

查看该类构造函数,里面最重要为调用了 nativeInit 接口。初始化相关数据,该方法为 c++ 方法。

// frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
public InputManagerService(Context context) {
        this.mContext = context;
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());

        mStaticAssociations = loadStaticInputPortAssociations();
        mUseDevInputEventForAudioJack =
                context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
        Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
                + mUseDevInputEventForAudioJack);
        // 初始化底层接口
        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());

        String doubleTouchGestureEnablePath = context.getResources().getString(
                R.string.config_doubleTouchGestureEnableFile);
        mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
            new File(doubleTouchGestureEnablePath);
        // 只能同进程使用
        LocalServices.addService(InputManagerInternal.class, new LocalService());
    }

nativeInit 方法初始化了 NativeInputManager 并把对应的指针地址转化为long类型返回。

// frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    // 创建消息队列
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == nullptr) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }
    // 初始化NativeInputManager
    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    // 将im指针转换为jlong类型,返回给java 后续其他对象可通过该值获取 NativeInputManager
    return reinterpret_cast<jlong>(im);
}

而 NativeInputManager 对应的构造函数又初始化了 InputManager,传入当前对象。

// frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();

    mServiceObj = env->NewGlobalRef(serviceObj);

    {
        AutoMutex _l(mLock);
        mLocked.systemUiLightsOut = false;
        mLocked.pointerSpeed = 0;
        mLocked.pointerGesturesEnabled = true;
        mLocked.showTouches = false;
        mLocked.pointerDisplayId = ADISPLAY_ID_DEFAULT;
    }
    mInteractive = true;
    // 初始化 InputManager
    InputManager* im = new InputManager(this, this);
    mInputManager = im;
    // 添加该服务到 sm 中 inputflinger
    defaultServiceManager()->addService(String16("inputflinger"), im);
}

InputManager 里又初始化了 InputDispatcher, InputClassifier,InputReader 等3个类。然后将 对应 InputDispatcher 作为参数传入 InputClassifier, 而 InputClassifier 又作为参数传入 InputReader里。所以可知 InputClassifier 作为 InputDispatcher 和 InputReader的中间沟通桥梁。事件读取后 通过 InputClassifier 通知 InputDispatcher 进行分发

// frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    // 通过 InputDispatcherFactory 创建 InputDispatcher
    mDispatcher = createInputDispatcher(dispatcherPolicy);
    // 将 dispatcher 传入 InputClassifier
    mClassifier = new InputClassifier(mDispatcher);
    // 通过 InputReaderFactory 创建 reader
    mReader = createInputReader(readerPolicy, mClassifier);
}

// frameworks/native/services/inputflinger/reader/InputReaderFactory.cpp
sp<InputReaderInterface> createInputReader(const sp<InputReaderPolicyInterface>& policy,
                                           const sp<InputListenerInterface>& listener) {
    return new InputReader(std::make_unique<EventHub>(), policy, listener);
}

// frameworks/native/services/inputflinger/dispatcher/InputDispatcherFactory.cpp
sp<InputDispatcherInterface> createInputDispatcher(
        const sp<InputDispatcherPolicyInterface>& policy) {
    return new android::inputdispatcher::InputDispatcher(policy);
}

而 InputReaderFactory 对 inputReader 的构造方法中,又初始化了 EventHub 类,作为参数传入,后续该类作为读取节点数据的作用。 EventHub 构造函数中 初始化了 Epoll, 并添加对应dev/input 文件夹删除和添加监听,和 getEvents 一样。

// frameworks/native/services/inputflinger/reader/EventHub.cpp
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
    mEpollFd = epoll_create1(EPOLL_CLOEXEC);
    LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
    // 跟getEvent一样 创建对应文件夹
    mINotifyFd = inotify_init();
    // 添加对dev/input增加和删除监听
    mInputWd = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
    LOG_ALWAYS_FATAL_IF(mInputWd < 0, "Could not register INotify for %s: %s", DEVICE_PATH,
                        strerror(errno));
    if (isV4lScanningEnabled()) {
        mVideoWd = inotify_add_watch(mINotifyFd, VIDEO_DEVICE_PATH, IN_DELETE | IN_CREATE);
        LOG_ALWAYS_FATAL_IF(mVideoWd < 0, "Could not register INotify for %s: %s",
                            VIDEO_DEVICE_PATH, strerror(errno));
    } else {
        mVideoWd = -1;
        ALOGI("Video device scanning disabled");
    }

    struct epoll_event eventItem = {};
    eventItem.events = EPOLLIN | EPOLLWAKEUP;
    eventItem.data.fd = mINotifyFd;
    // 添加到epoll监听中
    int result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add INotify to epoll instance.  errno=%d", errno);

    int wakeFds[2];
    result = pipe(wakeFds);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not create wake pipe.  errno=%d", errno);

    mWakeReadPipeFd = wakeFds[0];
    mWakeWritePipeFd = wakeFds[1];

    result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake read pipe non-blocking.  errno=%d",
                        errno);

    result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not make wake write pipe non-blocking.  errno=%d",
                        errno);

    eventItem.data.fd = mWakeReadPipeFd;
    result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mWakeReadPipeFd, &eventItem);
    LOG_ALWAYS_FATAL_IF(result != 0, "Could not add wake read pipe to epoll instance.  errno=%d",
                        errno);
}

总结 InputMangerService 会初始化一系列的变量。包含读取和分发相关类。并监听对应输入文件夹的变化。

InputManagerService 启动

初始化,就会启动对应的事件读取,开启一个循环不断进行读取对应的节点事件。
InputMangerService 通过start 方法进行开启

// frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
	t.traceBegin("StartInputManager");
    inputManager.setWindowManagerCallbacks(wm.getInputManagerCallback());
    // 通过start 启动事件监听循环
    inputManager.start();
    t.traceEnd();
}

进入start 方法查看,该方法主要进行相关配置的读取和监听,其中最重要的就是 nativeStart 方法。

public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);

        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);
        // 注册相关触摸监听设置
        registerPointerSpeedSettingObserver();
        ...
        updateBlockUntrustedTouchesModeFromSettings();
    }

查看 nativeStart 方法,该方法将传入的指针做转换为 NativeInputManager,并调用 里面 InputManger 的 start 方法。

// frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
    // 调用 NativeInputManager 里面的 inputManger 的start 方法
    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}

进入 start 方法,该方法 分别调用 inputReader 和 InputDispatcher 的 start 方法开启线程。

status_t InputManager::start() {
    status_t result = mDispatcher->start();
    if (result) {
        ALOGE("Could not start InputDispatcher thread due to error %d.", result);
        return result;
    }

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

        mDispatcher->stop();
        return result;
    }

    return OK;
}

以 inputReader 为例, 方法第一次 创建了 InputThread类,并将 loopOnce 函数作为参数传入 InputThread里

// frameworks/native/services/inputflinger/reader/InputReader.cpp
status_t InputReader::start() {
    if (mThread) {
        return ALREADY_EXISTS;
    }
    // 创建 InputThread 线程, 传入参数为 loopOnce 函数,等于里面 run 执行threadLoop方法时候会执行该函数
    mThread = std::make_unique<InputThread>(
            "InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });
    return OK;
}

InputThread 构造参数中, 又创建了线程类 InputThreadImpl 并通过 run 方法启动线程

// frameworks/native/services/inputflinger/InputThread.cpp
InputThread::InputThread(std::string name, std::function<void()> loop, std::function<void()> wake)
      : mName(name), mThreadWake(wake) {
    mThread = new InputThreadImpl(loop);
    // 创建后 执行run方法
    mThread->run(mName.c_str(), ANDROID_PRIORITY_URGENT_DISPLAY);
}

启动线程类后 会执行对应的 threadLoop 方法,而 threadLoop 又会执行 mThreadLoop 函数,该参数就是 InputRead 的 loopOnce 函数。这样就等于 loopOnce 函数循环读取对应设备节点事件,并处理。

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

总结 通过 start 方法 一步步调用到 inputReader 等start 方法并创建对应的线程类开始运作读取底层事件。

InputReader 事件的读取

启动线程后,会一直执行对应的 loopOnce 函数。该函数一开始判断对应的配置是否改变,改变则刷新,并通过 EventHub 的 getEvents 方法读取事件。

// frameworks/native/services/inputflinger/reader/InputReader.cpp
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;

        uint32_t changes = mConfigurationChangesToRefresh;
        if (changes) {
            mConfigurationChangesToRefresh = 0;
            timeoutMillis = 0;
            // 设置包含是否不包含节点设备
            refreshConfigurationLocked(changes);
        } 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);
        }

        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;
            inputDevices = getInputDevicesLocked();
        }
    } // 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();
}

进入 getEvents 方法。这里主要有个路径,如输入设备变化的注册和监听,已经设备事件输入的读取 。方法传入了 RawEvent数组 该数组和监听事件的 input_event 数组一样大小。

设备节点注册和监听

因为默认 mNeedToReopenDevices 为 false。所以第一个判断不会进入,接下来会判断是否有关闭的设备有的话 将创建对应的 RawEvent 对象 type 为 DEVICE_REMOVED。接下来 因为默认的 mNeedToScanDevices 为 true,所以会调用对应 的 scanDevicesLocked 对设备进行扫描。

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    ALOG_ASSERT(bufferSize >= 1);

    std::scoped_lock _l(mLock);
    // 跟 RawEvent 一样的大小
    struct input_event readBuffer[bufferSize];

    RawEvent* event = buffer;
    size_t capacity = bufferSize;
    bool awoken = false;
    for (;;) {
        nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);

        // Reopen input devices if needed.
        // 默认为false, 第一次会将 mNeedToScanDevices 变为true
        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.
        // 判断列表里面是否有关闭的设备,有的话向event数组添加对应的事件
        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 指向的元素,并更新迭代器 it 到下一个元素
            it = mClosingDevices.erase(it);
            mNeedToSendFinishedDeviceScan = true;
            if (--capacity == 0) {
                break;
            }
        }
        // 第一次为true, 通过 scanDevicesLocked 将对应的设备节点数据处理后放到 mOpeningDevices 数组中
        if (mNeedToScanDevices) {
            mNeedToScanDevices = false;
            scanDevicesLocked();
            mNeedToSendFinishedDeviceScan = true;
        }
        // 第一次不为空,会进入
        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;

            // Try to find a matching video device by comparing device names
            for (auto it = mUnattachedVideoDevices.begin(); it != mUnattachedVideoDevices.end();
                 it++) {
                std::unique_ptr<TouchVideoDevice>& videoDevice = *it;
                if (tryAddVideoDeviceLocked(*device, videoDevice)) {
                    // videoDevice was transferred to 'device'
                    it = mUnattachedVideoDevices.erase(it);
                    break;
                }
            }
            // 将对应 device 放到 mDevices map中
            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;
            }
        }
        // 有新增设备的时候,添加 finish事件
        if (mNeedToSendFinishedDeviceScan) {
            mNeedToSendFinishedDeviceScan = false;
            event->when = now;
            event->type = FINISHED_DEVICE_SCAN;
            event += 1;
            if (--capacity == 0) {
                break;
            }
        }
        ...

        // Report added or removed devices immediately.
        // 有设备变化则马上返回
        if (deviceChanged) {
            continue;
        }

        // Return now if we have collected any events or if we were explicitly awoken.
        // 如果有任何的事件则马上退出循环
        if (event != buffer || awoken) {
            break;
        }
        ...
    }

    // All done, return the number of events we read.
    return event - buffer;
}

scanDevicesLocked 又会通过对 scanDirLocked 方法进行扫描, 传入的 DEVICE_PATH 为 dev/input

// frameworks/native/services/inputflinger/reader/EventHub.cpp
void EventHub::scanDevicesLocked() {
    // dev/input 文件夹下
    status_t result = scanDirLocked(DEVICE_PATH);
    if (result < 0) {
        ALOGE("scan dir failed for %s", DEVICE_PATH);
    }
    if (isV4lScanningEnabled()) {
        result = scanVideoDirLocked(VIDEO_DEVICE_PATH);
        if (result != OK) {
            ALOGE("scan video dir failed for %s", VIDEO_DEVICE_PATH);
        }
    }
    if (mDevices.find(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID) == mDevices.end()) {
        createVirtualKeyboardLocked();
    }
}

scanDirLocked 通过 std::filesystem::directory_iterator 开始遍历。遍历到就调用 openDeviceLocked 方法

// 遍历文件夹下面的文件
status_t EventHub::scanDirLocked(const std::string& dirname) {
    for (const auto& entry : std::filesystem::directory_iterator(dirname)) {
        openDeviceLocked(entry.path());
    }
    return 0;
}

openDeviceLocked 方法,主要通过 open 加载对应节点文件符,并通过 ioctl 获取对应的设备信息,并将信息放到 InputDeviceIdentifier 实体类中,最终将 InputDeviceIdentifier 作为属性 放到 Device 实体类中, 在调用 registerDeviceForEpollLocked 注册到 epoll 中,最后通过 addDeviceLocked 放到 mOpeningDevices 数组中。

void EventHub::openDeviceLocked(const std::string& devicePath) {
	...
    // 判断是否已注册 注册就不用
    for (const auto& [deviceId, device] : mDevices) {
        if (device->path == devicePath) {
            return; // device was already registered
        }
    }

    char buffer[80];

    ALOGV("Opening device: %s", devicePath.c_str());
    // 打开对应的节点
    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 实体类
    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;
    }
    ...
    int32_t deviceId = mNextDeviceId++;
    // 生成 device实体类
    std::unique_ptr<Device> device = std::make_unique<Device>(fd, deviceId, devicePath, identifier);
	...
    // 添加到 epoll 中
    if (registerDeviceForEpollLocked(*device) != OK) {
        return;
    }

    device->configureFd();
	...
    // 添加到 mOpeningDevices 中
    addDeviceLocked(std::move(device));
}
status_t EventHub::registerDeviceForEpollLocked(Device& device) {
    status_t result = registerFdForEpoll(device.fd);
    if (result != OK) {
        ALOGE("Could not add input device fd to epoll for device %" PRId32, device.id);
        return result;
    }
    if (device.videoDevice) {
        registerVideoDeviceForEpollLocked(*device.videoDevice);
    }
    return result;
}

status_t EventHub::registerFdForEpoll(int fd) {
    // TODO(b/121395353) - consider adding EPOLLRDHUP
    struct epoll_event eventItem = {};
    eventItem.events = EPOLLIN | EPOLLWAKEUP;
    eventItem.data.fd = fd;
    if (epoll_ctl(mEpollFd, EPOLL_CTL_ADD, fd, &eventItem)) {
        ALOGE("Could not add fd to epoll instance: %s", strerror(errno));
        return -errno;
    }
    return OK;
}
// frameworks/native/services/inputflinger/reader/EventHub.cpp
void EventHub::addDeviceLocked(std::unique_ptr<Device> device) {
    reportDeviceAddedForStatisticsLocked(device->identifier, device->classes);
    mOpeningDevices.push_back(std::move(device));
}

扫描完成后,添加到 mOpeningDevices 数组,即该数组不为空,回到 getEvents 方法中 则会进入判断,遍历对应的数组,并添加 RawEvent事件对应的,type为 DEVICE_ADDED。并将对应devvice 放到对应 map中。最后因为有设备添加又会添加 FINISHED_DEVICE_SCAN 事件。因为事件和数组不相等会进入break,退出循环。这样设备节点的添加和监听就完成。

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
			....
			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;

            // Try to find a matching video device by comparing device names
            for (auto it = mUnattachedVideoDevices.begin(); it != mUnattachedVideoDevices.end();
                 it++) {
                std::unique_ptr<TouchVideoDevice>& videoDevice = *it;
                if (tryAddVideoDeviceLocked(*device, videoDevice)) {
                    // videoDevice was transferred to 'device'
                    it = mUnattachedVideoDevices.erase(it);
                    break;
                }
            }
            // 将对应 device 放到 mDevices map中
            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;
            }
        }
        // 有新增设备的时候,添加 finish事件
        if (mNeedToSendFinishedDeviceScan) {
            mNeedToSendFinishedDeviceScan = false;
            event->when = now;
            event->type = FINISHED_DEVICE_SCAN;
            event += 1;
            if (--capacity == 0) {
                break;
            }
        }
        ...
		// 如果有任何的事件则马上退出循环
        if (event != buffer || awoken) {
            break;
        }
}

设备输入事件的读取

当添加完又会进入下一个循环,再一次进入 getEvents方法。进入后 即会进入 epoll_wait等待输入事件,当事件返回后,则将对应的数量赋值给 mPendingEventCount ,最后又进入下一次循环。

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
		...
		mPendingEventIndex = 0;

        mLock.unlock(); // release lock before poll
        // epoll在等待消息产生,产生消息EventItem都会放到 mPendingEventItems 中,会跟mPendingEventCount比较
        int pollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS, timeoutMillis);

        mLock.lock(); // reacquire lock after poll

        if (pollResult == 0) {
            // Timed out.
            mPendingEventCount = 0;
            break;
        }

        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.
            // 有多少个输入事件
            mPendingEventCount = size_t(pollResult);
        }
}

进入下一次循环后, mPendingEventCount 不为0 ,则会大于 mPendingEventIndex 进入事件的读取,判断对应的fd类型,进行相对应的处理。在通过 getDeviceByFdLocked 从 map中获取对应的device。在通过 read 函数读取对应的数据,并判断是否是input_event的整数倍,不是则为异常数据。最后在读取相关的 code,type,value。放到 RawEvent 中。并返回。

size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
		...
		// 有相关输入事件的时候走这里
        bool deviceChanged = false;
        while (mPendingEventIndex < mPendingEventCount) {
            const struct epoll_event& eventItem = mPendingEventItems[mPendingEventIndex++];
            if (eventItem.data.fd == mINotifyFd) {
                if (eventItem.events & EPOLLIN) {
                    mPendingINotify = true;
                } else {
                    ALOGW("Received unexpected epoll event 0x%08x for INotify.", eventItem.events);
                }
                continue;
            }

            if (eventItem.data.fd == mWakeReadPipeFd) {
                if (eventItem.events & EPOLLIN) {
                    ALOGV("awoken after wake()");
                    awoken = true;
                    char wakeReadBuffer[16];
                    ssize_t nRead;
                    do {
                        nRead = read(mWakeReadPipeFd, wakeReadBuffer, sizeof(wakeReadBuffer));
                    } while ((nRead == -1 && errno == EINTR) || nRead == sizeof(wakeReadBuffer));
                } else {
                    ALOGW("Received unexpected epoll event 0x%08x for wake read pipe.",
                          eventItem.events);
                }
                continue;
            }
            // 通过文件描述符获取对应的设备节点
            Device* device = getDeviceByFdLocked(eventItem.data.fd);
            if (device == nullptr) {
                ALOGE("Received unexpected epoll event 0x%08x for unknown fd %d.", eventItem.events,
                      eventItem.data.fd);
                ALOG_ASSERT(!DEBUG);
                continue;
            }
            ...
            // This must be an input event
            // 输入事件处理
            if (eventItem.events & EPOLLIN) {
                int32_t readSize =
                        read(device->fd, readBuffer, sizeof(struct input_event) * capacity);
                if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
                    // Device was removed before INotify noticed.
                    ALOGW("could not get event, removed? (fd: %d size: %" PRId32
                          " bufferSize: %zu capacity: %zu errno: %d)\n",
                          device->fd, readSize, bufferSize, capacity, errno);
                    deviceChanged = true;
                    closeDeviceLocked(*device);
                } else if (readSize < 0) {
                    if (errno != EAGAIN && errno != EINTR) {
                        ALOGW("could not get event (errno=%d)", errno);
                    }
                } else if ((readSize % sizeof(struct input_event)) != 0) {
                    // 一定是inputEvent的整数倍
                    ALOGE("could not get event (wrong size: %d)", readSize);
                } else {
                    int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
                    // 一定是inputEvent的整数倍
                    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;
                    }
                    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;
                    }
                }
            } else if (eventItem.events & EPOLLHUP) {
                ALOGI("Removing device %s due to epoll hang-up event.",
                      device->identifier.name.c_str());
                deviceChanged = true;
                closeDeviceLocked(*device);
            } else {
                ALOGW("Received unexpected epoll event 0x%08x for device %s.", eventItem.events,
                      device->identifier.name.c_str());
            }
        }
}

总结 事件的读取 通过 getEvents 注册和监听各种事件 并组装成RawEvents实体类返回,如 底层的 input_event 转化为 RawEvents。

InputReader 事件的处理

getEvents 获取后,则要进行事件的处理,processEventsLocked 进行事件的处理。是事件的处理分为 输入事件 和 设备的添加 移除 扫描结束等。

void InputReader::loopOnce() {
	...
	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);
        }
		...
    } // release lock
}

processEventsLocked 开始依次遍历对应的 rawEvents ,因为 DEVICE_ADDED定义的值很大,所以低于 DEVICE_ADDED 都作为输入事件。

// frameworks/native/services/inputflinger/reader/include/EventHub.h
DEVICE_ADDED = 0x10000000,
// Sent when a device is removed.
DEVICE_REMOVED = 0x20000000,
// Sent when all added/removed devices from the most recent scan have been reported.
// This event is always sent at least once.
FINISHED_DEVICE_SCAN = 0x30000000,

FIRST_SYNTHETIC_EVENT = DEVICE_ADDED,

// frameworks/native/services/inputflinger/reader/InputReader.cpp
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count;) {
        int32_t type = rawEvent->type;
        size_t batchSize = 1;
        // 输入触摸事件
        // 比 DEVICE_ADDED 小于都是输入事件
        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;
    }
}

设备的添加和删除处理

以添加为例,可以看到调用了 addDeviceLocked 方法,该方法 又通过 createDeviceLocked 方法创建对应的 InputDevice 设备 ,将对应的 设备添加 mDevices map中。(这里将getEvents中的 device 又转化为了 InputDevice中)。

void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
    if (mDevices.find(eventHubId) != mDevices.end()) {
        ALOGW("Ignoring spurious device added event for eventHubId %d.", eventHubId);
        return;
    }
    // 从 mDevices 获取对应的device中的 InputDeviceIdentifier
    InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
    // 创建对应 InputDevice, 添加到 inputReader的 mdevices中,指定了对应mapper 用于后续的事件处理
    std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
    device->configure(when, &mConfig, 0);
    device->reset(when);

    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.
    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);
    }
    bumpGenerationLocked();

    if (device->getClasses().test(InputDeviceClass::EXTERNAL_STYLUS)) {
        notifyExternalStylusPresenceChangedLocked();
    }

    // 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.
    if (mEventHub->getDeviceClasses(eventHubId).test(InputDeviceClass::SENSOR)) {
        mEventHub->disableDevice(eventHubId);
    }
}

createDeviceLocked 方法中 最重要的方法是 addEventHubDevice 方法 该方法根据对应的设备类型,添加对应的mapper。而mapper作为后续输入事件对应的处理方法

std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
        int32_t eventHubId, const InputDeviceIdentifier& identifier) {
    // 通过 find_if 搜索对应的 看是否有对应的
    auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {
        return devicePair.second->getDescriptor().size() && identifier.descriptor.size() &&
                devicePair.second->getDescriptor() == identifier.descriptor;
    });

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

addEventHubDevice 通过对应的class 判断,这里分析的是多指触摸,所以添加的 mapper 为 MultiTouchInputMapper

// frameworks/native/services/inputflinger/reader/InputDevice.cpp
void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
    // 如果存在则不处理
    if (mDevices.find(eventHubId) != mDevices.end()) {
        return;
    }
    std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));
    Flags<InputDeviceClass> classes = contextPtr->getDeviceClasses();
    std::vector<std::unique_ptr<InputMapper>> mappers;

    // Check if we should skip population
	...
    // Touchscreens and touchpad devices.
    // 如果是触摸的,分多指和单指,大部分都是单指
    if (classes.test(InputDeviceClass::TOUCH_MT)) {
        mappers.push_back(std::make_unique<MultiTouchInputMapper>(*contextPtr));
    } else if (classes.test(InputDeviceClass::TOUCH)) {
        mappers.push_back(std::make_unique<SingleTouchInputMapper>(*contextPtr));
    }

    // Joystick-like devices.
    if (classes.test(InputDeviceClass::JOYSTICK)) {
        mappers.push_back(std::make_unique<JoystickInputMapper>(*contextPtr));
    }
    ...

    // insert the context into the devices set
    mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
    // Must change generation to flag this device as changed
    bumpGeneration();
}

总结 添加和删除 将 device转化为 InputDevice,生成的时候 添加对应的事件处理mapper。并方法 mDevices map中,移除则为移除该设备从map中。

触摸事件的处理

触摸事件会将同个设备一系列事件,通过 processEventsForDeviceLocked 进行处理。

// frameworks/native/services/inputflinger/reader/InputReader.cpp
			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); // 处理事件

该方法里面又会通过 eventHubId 获取对应的InputDevice,并调用 process 方法进行处理

// frameworks/native/services/inputflinger/reader/InputReader.cpp
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;
    // mapper为空,不处理
    if (device->isIgnored()) {
        // ALOGD("Discarding event for ignored deviceId %d.", deviceId);
        return;
    }

    device->process(rawEvents, count);
}

InputDevice 的 process 方法又会将之前设备添加 mapper 进行遍历,之前说过多指触摸的mapper 为 MultiTouchInputMapper ,所以会调用到他的 process 方法。

// frameworks/native/services/inputflinger/reader/InputDevice.cpp
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
		...
        } else {
            for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
                // 多指触碰是 MultiTouchMotionAccumulator
                mapper.process(rawEvent);
            });
        }
        --count;
    }
}

对应的 process 方法第一步 先进入 TouchInputMapper::process, 但是该方法里面判断为系列事件结束才会进入,所以事件刚开始并不会执行里面逻辑,而是执行 下一个方法。而 mMultiTouchMotionAccumulator.process 则是将对应 type 为 EV_ABS 进行读取 并赋值到 Slot 实体中,最终再由 TouchInputMapper 结束事件统一处理。

// 先执行这个方法
void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
    // 处理sync SYN_REPORT 事件
    TouchInputMapper::process(rawEvent);
    // 处理ABS事件
    mMultiTouchMotionAccumulator.process(rawEvent);
}

最大支持触摸为16个, 其中 mCurrentSlot 是通过底层驱动给的值并通过 mSlots 中获取对应 Slot 实体类在将拿的值和类型填充到对应的属性。注意如果 ABS_MT_TRACKING_ID 为负数,则表示抬起,所以 mInUse 会被值为 false。

// frameworks/native/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
    if (rawEvent->type == EV_ABS) {
        bool newSlot = false;
        // 是否符合多指触摸的b协议
        if (mUsingSlotsProtocol) {
            // 代表一个触摸点,接下来所有事件属于这个触摸点
            if (rawEvent->code == ABS_MT_SLOT) {
                mCurrentSlot = rawEvent->value;
                newSlot = true;
            }
        } else if (mCurrentSlot < 0) {
            mCurrentSlot = 0;
        }
        // 最大支持16个手指
        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 {
            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;
            }
            // 根据对应的code 将对应的值 赋值到 slot属性中
            switch (rawEvent->code) {
                case ABS_MT_POSITION_X:
                    slot->mAbsMTPositionX = rawEvent->value;
                    warnIfNotInUse(*rawEvent, *slot);
                    break;
                case ABS_MT_POSITION_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:
                    // 对应ID 如果是 FFFFFFF 小于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;
    }
}

组装好 slot数据后,就会进入到事件结束标志位 SYN_REPORT,所以会调用 sync 方法。

// frameworks/native/services/inputflinger/reader/mapper/TouchInputMapper.cpp
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);
    }
}

进入 sync 方法,会拿出 RawState 对象并进行清空 操作。在调用 syncTouch 方法。该方法即为 MultiTouchInputMapper.cpp 的 syncTouch 方法。

// frameworks/native/services/inputflinger/reader/mapper/TouchInputMapper.cpp
void TouchInputMapper::sync(nsecs_t when, nsecs_t readTime) {
    // Push a new state.
    mRawStatesPending.emplace_back();
    // 获取rawState,并对变量进行重置
    RawState& next = mRawStatesPending.back();
    next.clear();
    next.when = when;
    next.readTime = readTime;

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

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

    // Sync touch
    // 调用多指 MultiTouchInputMapper的syncTouch
    syncTouch(when, &next);

    // The last RawState is the actually second to last, since we just added a new state
    const RawState& last =
            mRawStatesPending.size() == 1 ? mCurrentRawState : mRawStatesPending.rbegin()[1];

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

	...
    // 对数据进行加工
    processRawTouches(false /*timeout*/);
}

回到 MultiTouchInputMapper 中, 该返回获取对应的事件数量,并进行遍历。判断到 isInUse 为 false 表示抬起 不处理。接着从 outState 取出 RawPointerData类,因为上一部已经清空,所以里面不会有内容。并将值赋值给了他。

里面有比较重要的属性是 idToIndex 以及 id。他对应了 ToucheEvent里面的 index 和他对应的value 。由一个32位的int值控制,从高位开始排起,记录每个手指对应的id。

第一步: mPointerIdBits 赋值给临时的 idBits,并通过 clearFirstMarkedBit (先获取对应的前导0,在将该位1值为0),获取到对应的位数后,在从 mPointerTrackingIdMap 判断是否和 trackingId相等 相等则表示id 为n, 不相等则进入下一步

第二步:当id小于0 , 则通过 markFirstUnmarkedBit (对该数值取反得到前导0,在将该位变1),并将前导0 作为该id。

第三步:将对应的 outCount(outCount遍历一次加1) 赋值给index,id赋值给id。并通过markBit(针对哪位变为1) 对 newPointerIdBits 新变量 记录 有手指的标志位 。因为抬起的时候需要将该位变为0,上面只是添加,所以最后在将 newPointerIdBits 赋值给 mPointerIdBits,用于下一次事件的判断。

void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
    size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
    size_t outCount = 0;
    BitSet32 newPointerIdBits;
    mHavePointerIds = true;

    for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
        const MultiTouchMotionAccumulator::Slot* inSlot =
                mMultiTouchMotionAccumulator.getSlot(inIndex);
        // 抬起为false不处理
        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());
#endif
            continue;
        }

        if (outCount >= MAX_POINTERS) {
#if DEBUG_POINTERS
            ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
                  "ignoring the rest.",
                  getDeviceName().c_str(), MAX_POINTERS);
#endif
            break; // too many fingers!
        }
        // 将数据从slot 转化为rawPointerData, 拿出来为空的.outState传进来已被清空
        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.
        // 处理事件 touch 里面 index 以值的关系
        if (mHavePointerIds) {
            // 获取对应的ID
            int32_t trackingId = inSlot->getTrackingId();
            int32_t id = -1;
            if (trackingId >= 0) {
                // 将mPointerIdBits 赋值给idBits,第一次为0,
                for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty();) {
                    // 拿前导位有多少 然后清空当前的位为0
                    uint32_t n = idBits.clearFirstMarkedBit();
                    // 从map拿出 如果相等则id赋值给他
                    if (mPointerTrackingIdMap[n] == trackingId) {
                        id = n;
                    }
                }

                if (id < 0 && !mPointerIdBits.isFull()) {
                    // 如果没找到,则取反返回前导0的位,并将该位置为1,并保存到map中
                    id = mPointerIdBits.markFirstUnmarkedBit();
                    mPointerTrackingIdMap[id] = trackingId;
                }
            }
            if (id < 0) {
                mHavePointerIds = false;
                outState->rawPointerData.clearIdBits();
                newPointerIdBits.clear();
            } else {
                // 对应值
                outPointer.id = id;
                // 对应touchEvent的 index,当2个手指按下抬起第一个,outCount变为0,id依旧为1
                outState->rawPointerData.idToIndex[id] = outCount;
                outState->rawPointerData.markIdBit(id, isHovering);
                // 标记下新的位数,因为前面mPointerIdBits 不会清除,比如抬起第一个手指 这时候mPointerIdBits 还是1100000
                // 所以要用新的变量记录最新的手指按下情况
                newPointerIdBits.markBit(id);
            }
        }
        outCount += 1;
    }
    // 记录手指数量
    outState->rawPointerData.pointerCount = outCount;
    // 赋值给 newPointerIdBits 这样抬起的位数就变为0
    mPointerIdBits = newPointerIdBits;

    mMultiTouchMotionAccumulator.finishSync();
}

对应32位工具类方法的讲解

// system/core/libutils/include/utils/BitSet.h
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef UTILS_BITSET_H
#define UTILS_BITSET_H

#include <stdint.h>
#include <utils/TypeHelpers.h>

/*
 * A class to provide efficient manipulation of bitsets.
 *
 * Consider using std::bitset<32> or std::bitset<64> if all you want is a class to do basic bit
 * manipulation (i.e. AND / OR / XOR / flip / etc). These classes are only needed if you want to
 * efficiently perform operations like finding the first set bit in a bitset and you want to
 * avoid using the built-in functions (e.g. __builtin_clz) on std::bitset::to_ulong.
 */

namespace android {

// A simple set of 32 bits that can be individually marked or cleared.
struct BitSet32 {
    uint32_t value;

    inline BitSet32() : value(0UL) { }
    explicit inline BitSet32(uint32_t value) : value(value) { }

    // Gets the value associated with a particular bit index.
    // 函数作用表示向右移动多少位
    // 0x80000000UL 32位数表示为 10000000000000000000000000000000
    static inline uint32_t valueForBit(uint32_t n) { return 0x80000000UL >> n; }

    // Clears the bit set.
    inline void clear() { clear(value); }

    static inline void clear(uint32_t& value) { value = 0UL; }

    // Returns the number of marked bits in the set.
    inline uint32_t count() const { return count(value); }

    static inline uint32_t count(uint32_t value) {
        return static_cast<uint32_t>(__builtin_popcountl(value));
    }

    // Returns true if the bit set does not contain any marked bits.
    inline bool isEmpty() const { return isEmpty(value); }

    static inline bool isEmpty(uint32_t value) { return ! value; }

    // Returns true if the bit set does not contain any unmarked bits.
    inline bool isFull() const { return isFull(value); }

    static inline bool isFull(uint32_t value) { return value == 0xffffffffUL; }

    // Returns true if the specified bit is marked.
    inline bool hasBit(uint32_t n) const { return hasBit(value, n); }

    static inline bool hasBit(uint32_t value, uint32_t n) { return value & valueForBit(n); }

    // Marks the specified bit.
    inline void markBit(uint32_t n) { markBit(value, n); }

    static inline void markBit (uint32_t& value, uint32_t n) { value |= valueForBit(n); }

    // Clears the specified bit.
    // 向右移动多少位在取反,在与运算,等于保留其他位,将特定的位取反
    inline void clearBit(uint32_t n) { clearBit(value, n); }

    static inline void clearBit(uint32_t& value, uint32_t n) { value &= ~ valueForBit(n); }

    // Finds the first marked bit in the set.
    // Result is undefined if all bits are unmarked.
    inline uint32_t firstMarkedBit() const { return firstMarkedBit(value); }

    static uint32_t firstMarkedBit(uint32_t value) { return clz_checked(value); }

    // Finds the first unmarked bit in the set.
    // Result is undefined if all bits are marked.
    inline uint32_t firstUnmarkedBit() const { return firstUnmarkedBit(value); }

    static inline uint32_t firstUnmarkedBit(uint32_t value) { return clz_checked(~ value); }

    // Finds the last marked bit in the set.
    // Result is undefined if all bits are unmarked.
    inline uint32_t lastMarkedBit() const { return lastMarkedBit(value); }

    static inline uint32_t lastMarkedBit(uint32_t value) { return 31 - ctz_checked(value); }

    // Finds the first marked bit in the set and clears it.  Returns the bit index.
    // Result is undefined if all bits are unmarked.
    // 第一步先获取前导0多少位,则第一个为1前面多少位0
    // 第二步清除对应位数的1变为0
    // 返回前面有多少位
    inline uint32_t clearFirstMarkedBit() { return clearFirstMarkedBit(value); }

    static inline uint32_t clearFirstMarkedBit(uint32_t& value) {
        uint32_t n = firstMarkedBit(value);
        clearBit(value, n);
        return n;
    }

    // Finds the first unmarked bit in the set and marks it.  Returns the bit index.
    // Result is undefined if all bits are marked.
    // 1.先获取前导数量为0的个数
    // 2.对对应的位数标记为1
    // 3.返回前导数量
    inline uint32_t markFirstUnmarkedBit() { return markFirstUnmarkedBit(value); }

    static inline uint32_t markFirstUnmarkedBit(uint32_t& value) {
        uint32_t n = firstUnmarkedBit(value);
        markBit(value, n);
        return n;
    }

    // Finds the last marked bit in the set and clears it.  Returns the bit index.
    // Result is undefined if all bits are unmarked.
    inline uint32_t clearLastMarkedBit() { return clearLastMarkedBit(value); }

    static inline uint32_t clearLastMarkedBit(uint32_t& value) {
        uint32_t n = lastMarkedBit(value);
        clearBit(value, n);
        return n;
    }

    // Gets the index of the specified bit in the set, which is the number of
    // marked bits that appear before the specified bit.
    inline uint32_t getIndexOfBit(uint32_t n) const {
        return getIndexOfBit(value, n);
    }

    static inline uint32_t getIndexOfBit(uint32_t value, uint32_t n) {
        return static_cast<uint32_t>(__builtin_popcountl(value & ~(0xffffffffUL >> n)));
    }

    inline bool operator== (const BitSet32& other) const { return value == other.value; }
    inline bool operator!= (const BitSet32& other) const { return value != other.value; }
    inline BitSet32 operator& (const BitSet32& other) const {
        return BitSet32(value & other.value);
    }
    inline BitSet32& operator&= (const BitSet32& other) {
        value &= other.value;
        return *this;
    }
    inline BitSet32 operator| (const BitSet32& other) const {
        return BitSet32(value | other.value);
    }
    inline BitSet32& operator|= (const BitSet32& other) {
        value |= other.value;
        return *this;
    }

private:
    // We use these helpers as the signature of __builtin_c{l,t}z has "unsigned int" for the
    // input, which is only guaranteed to be 16b, not 32. The compiler should optimize this away.
    static inline uint32_t clz_checked(uint32_t value) {
        if (sizeof(unsigned int) == sizeof(uint32_t)) {
            return static_cast<uint32_t>(__builtin_clz(value));
        } else {
            return static_cast<uint32_t>(__builtin_clzl(value));
        }
    }

    static inline uint32_t ctz_checked(uint32_t value) {
        if (sizeof(unsigned int) == sizeof(uint32_t)) {
            return static_cast<uint32_t>(__builtin_ctz(value));
        } else {
            return static_cast<uint32_t>(__builtin_ctzl(value));
        }
    }
};

ANDROID_BASIC_TYPES_TRAITS(BitSet32)

// A simple set of 64 bits that can be individually marked or cleared.
struct BitSet64 {
    uint64_t value;

    inline BitSet64() : value(0ULL) { }
    explicit inline BitSet64(uint64_t value) : value(value) { }

    // Gets the value associated with a particular bit index.
    // 右移动几位
    static inline uint64_t valueForBit(uint32_t n) { return 0x8000000000000000ULL >> n; }

    // Marks the specified bit.
    // 对该位赋值为1
    inline void markBit(uint32_t n) { markBit(value, n); }

    static inline void markBit(uint64_t& value, uint32_t n) { value |= valueForBit(n); }

    // Clears the specified bit.
    inline void clearBit(uint32_t n) { clearBit(value, n); }

    static inline void clearBit(uint64_t& value, uint32_t n) { value &= ~ valueForBit(n); }

    // Finds the first marked bit in the set.
    // Result is undefined if all bits are unmarked.
    // 输出前导为0的个数,如 8 32位数
    // 0000 0000 0000 0000 0000 0000 0000 1000  28个前导0 输出28
    inline uint32_t firstMarkedBit() const { return firstMarkedBit(value); }

    static inline uint32_t firstMarkedBit(uint64_t value) {
        return static_cast<uint32_t>(__builtin_clzll(value));
    }

    // Finds the first unmarked bit in the set.
    // Result is undefined if all bits are marked.
    // 输出前导为0的个数,如 8 32位数
    // 注意这里取反获取
    //       1000 0000 0000 0000 0000 0000 0000 0000
    // 取反得 0111 1111 1111 1111 1111 1111 1111 1111
    // 返回1
    inline uint32_t firstUnmarkedBit() const { return firstUnmarkedBit(value); }

    static inline uint32_t firstUnmarkedBit(uint64_t value) {
        return static_cast<uint32_t>(__builtin_clzll(~value));
    }

    // Finds the first unmarked bit in the set and marks it.  Returns the bit index.
    // Result is undefined if all bits are marked.
    // 1.先获取前导数量为0的个数 里面做了取反
    // 2.对对应的位数标记为1
    // 3.返回前导数量
    inline uint32_t markFirstUnmarkedBit() { return markFirstUnmarkedBit(value); }

    static inline uint32_t markFirstUnmarkedBit(uint64_t& value) {
        uint32_t n = firstUnmarkedBit(value);
        markBit(value, n);
        return n;
    }
};

ANDROID_BASIC_TYPES_TRAITS(BitSet64)

} // namespace android

#endif // UTILS_BITSET_H

总结 输入事件 先将对应的RawEvent 转化为 slot 类,在将 slot类转化为 RawPointerData,并算出触摸对应的id 和index。

数据的加工和分发

事件处理完后, 要到 inputDispatcher 还需要进一步的加工 ,执行完 syncTouch后,调用 processRawTouches。对事件进行一个加工。

void TouchInputMapper::sync(nsecs_t when, nsecs_t readTime) {
    // Push a new state.
    mRawStatesPending.emplace_back();
    // 获取rawState,并对变量进行重置
    RawState& next = mRawStatesPending.back();
    next.clear();
    next.when = when;
    next.readTime = readTime;

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

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

    // Sync touch
    // 调用多指 MultiTouchInputMapper的syncTouch
    syncTouch(when, &next);
    ...
    // 对数据进行加工
    processRawTouches(false /*timeout*/);
}

查看对应的方法,一开始对 mDeviceMode属性进行判断,如果为 disable 则不处理事件。然后会调用 cookAndDispatch 方法进行事件的处理和分发。

// frameworks/native/services/inputflinger/reader/mapper/TouchInputMapper.cpp
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.
    const size_t N = mRawStatesPending.size();
    size_t count;
    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;
        }

        // All ready to go.
        clearStylusDataPendingFlags();
        mCurrentRawState.copyFrom(next);
        if (mCurrentRawState.when < mLastRawState.when) {
            mCurrentRawState.when = mLastRawState.when;
            mCurrentRawState.readTime = mLastRawState.readTime;
        }
        // 加工和分发
        cookAndDispatch(mCurrentRawState.when, mCurrentRawState.readTime);
    }
    if (count != 0) {
        mRawStatesPending.erase(mRawStatesPending.begin(), mRawStatesPending.begin() + 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
            const nsecs_t readTime = when; // consider this synthetic event to be zero latency
            cookAndDispatch(when, readTime);
        } else if (mExternalStylusFusionTimeout == LLONG_MAX) {
            mExternalStylusFusionTimeout = mExternalStylusState.when + TOUCH_DATA_TIMEOUT;
            getContext()->requestTimeoutAtTime(mExternalStylusFusionTimeout);
        }
    }
}

cookAndDispatch 方法 主要对 2步

  1. 调用 cookPointerData 将数据做一个转换,将对应的RawPointerData 加工为 PointerCoords,主要对数据跟设备的配置参数做一个校准,进行相对的转换,转换x ,y 符合屏幕数据
  2. 调用 dispatchTouches, 对事件是 down 还是 move ,up进行判断。
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;
        }
    }

    // Consume raw off-screen touches before cooking pointer data.
    // If touches are consumed, subsequent code will not receive any pointer data.
    // 消费屏幕外的输入事件
    if (consumeRawTouches(when, readTime, 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.
    // 将对应的RawPointerData 加工为 PointerCoords
    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, readTime, getDeviceId(),
                         mSource, mViewport.displayId, policyFlags, mLastCookedState.buttonState,
                         mCurrentCookedState.buttonState);

    // Dispatch the touches either directly or by translation through a pointer on screen.
    if (mDeviceMode == DeviceMode::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 = PointerUsage::STYLUS;
        } else if (!mCurrentCookedState.mouseIdBits.isEmpty()) {
            mCurrentCookedState.fingerIdBits.clear();
            pointerUsage = PointerUsage::MOUSE;
        } else if (!mCurrentCookedState.fingerIdBits.isEmpty() ||
                   isPointerDown(mCurrentRawState.buttonState)) {
            pointerUsage = PointerUsage::GESTURES;
        }

        dispatchPointerUsage(when, readTime, policyFlags, pointerUsage);
    } else {
        updateTouchSpots();

        if (!mCurrentMotionAborted) {
            dispatchButtonRelease(when, readTime, policyFlags);
            dispatchHoverExit(when, readTime, policyFlags);
            // 对事件进行分发,判断是move 还是down,up事件
            dispatchTouches(when, readTime, policyFlags);
            dispatchHoverEnterAndMove(when, readTime, policyFlags);
            dispatchButtonPress(when, readTime, policyFlags);
        }

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

    // Synthesize key up from raw buttons if needed.
    synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, readTime, getDeviceId(), mSource,
                         mViewport.displayId, 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);
}

cookPointerData 方法 ,开始遍历并通过 scale 等参数进行数据的转换,转换后存到 PointerCoords 中。

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
    // surface coordinates and adjust for display orientation.
    for (uint32_t i = 0; i < currentPointerCount; i++) {
        const RawPointerData::Pointer& in = mCurrentRawState.rawPointerData.pointers[i];
        ...
        // Distance
        float distance;
        switch (mCalibration.distanceCalibration) {
            case Calibration::DistanceCalibration::SCALED:
                distance = in.distance * mDistanceScale;
                break;
            default:
                distance = 0;
        }

        // Adjust X,Y coords for device calibration
        // TODO: Adjust coverage coords?
        // 转化为浮点数
        float xTransformed = in.x, yTransformed = in.y;
        mAffineTransform.applyTo(xTransformed, yTransformed);
        // 获取对应的x,y坐标
        rotateAndScale(xTransformed, yTransformed);

        // Adjust X, Y, and coverage coords for surface orientation.
        float left, top, right, bottom;
        // 根据屏幕方向算出对应的left right
        switch (mSurfaceOrientation) {
            case DISPLAY_ORIENTATION_90:
                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:
                left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
                right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
                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:
                left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
                right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
                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:
                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
        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 id index and mark id as valid.
        // 对应的index和id
        mCurrentCookedState.cookedPointerData.idToIndex[id] = i;
        mCurrentCookedState.cookedPointerData.validIdBits.markBit(id);
    }
}

参数的读取 可以按以下方法。
执行 getevent -ltr 然后触摸获取对应的 触摸点 如获取到的为 /dev/input/event7
然后在执行 dumpsys input 获取对应的信息,然后看对应的名称,如下图 /dev/input/event7 对应的是 synaptics_tcm_touch
在这里插入图片描述
在通过查看对应的设备7 则可以看到相关的信息
在这里插入图片描述

dispatchTouches 方法中,则通过上一个事件的bit和当前的bit位,比较获取判断事件类型。
如果前后int值相等,则肯定为 move事件
在通过与或判断是否有按下或者抬起事件,需要注意 move事件判断是否

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.
        // 取出抬起的
        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.
        // 判断移动的bits是否坐标一样,不一样需要移动
        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.
        // 遍历抬起的id,传递up事件
        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.
        // 如果down不为空,遍历下
        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);
        }
    }
}

dispatchMotion 将传入的参数进行判断,最终整合为 NotifyMotionArgs 参数 通过 getListener()->notifyMotion 方法放进去堆栈。

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) {
    ...
    // 变成 NotifyMotionArgs
    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));
    // 丢到数组里面的 通过flush刷新数据
    getListener()->notifyMotion(&args);
}

最终在 loopOnce 执行循环后 执行 flush 将堆栈里面的内容遍历 拿出来进行通知。

void InputReader::loopOnce() {
    ...
    // 读取完从队列调用通知
    mQueuedListener->flush();
}

总结 将分析对应的事件是down还是 move事件 最终 PointerCoords 转化为 NotifyMotionArgs 再放进数组 然后在通过 flush 进行刷新。

  • 17
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值