原计划 input 输入事件的学习分为两节内容学习并记录,经学习发现并远不止这些内容,所以决定重新写 input 输入事件番外篇,如需参考,请阅读 input 输入事件番外篇;造成的不便,深表抱歉。
1. InputManagerService的启动:安卓系统服务的启动都是在 SystemServer 这个进程中,我们可以在main()方法调用的 new SystemServer().run() 中找打如下代码:
inputManager = new InputManagerService(context); // 构建InputManagerService对象,见1.1
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
mActivityManagerService.setWindowManager(wm);
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start(); // 执行start()方法,见1.2
1.1 InputManagerService 的构造函数:
// InputManagerService.java中:构造函数
public InputManagerService(Context context) {
this.mContext = context;
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
// native方法,com_android_server_input_InputManagerService.cpp中
mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
我们在看看这个native方法:frameworks/base/services/core/jni目录中
// native方法,com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass clazz,
jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
// MessageQueue的指针
sp messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
if (messageQueue == NULL) {
jniThrowRuntimeException(env, "MessageQueue is not initialized.");
return 0;
}
// 就是这个对象
NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
messageQueue->getLooper());
im->incStrong(0);
return reinterpret_cast(im);
}
// native方法,com_android_server_input_InputManagerService.cpp
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp& looper) :
mLooper(looper), mInteractive(true) {
// ...
sp eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}
上面的代码中创建了一个 NativeInputManager 对象,并且把这个对象返回了保存在 InputManagerService的 mPtr 中;然后再看看 new InputManager(eventHub, this, this):
// InputManager.cpp中:
InputManager::InputManager(
const sp& eventHub,
const sp& readerPolicy,
const sp& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);
// 传入mDispatcher:读到的信号,肯定是要通过 mDispatcher 回调的
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
// InputManager.cpp中:
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
到这里,我们就获取到和输入事件相关的几个关键类:EventHub、InputReader、InputDispatcher;另外 InputReaderThread 和 InputDispatcherThread 就是两条处理线程;
1.2 执行start()方法:inputManager.start();
public void start() {
Slog.i(TAG, "Starting input manager");
nativeStart(mPtr); // native 方法:关键代码
// Add ourself to the Watchdog monitors.
Watchdog.getInstance().addMonitor(this);
registerPointerSpeedSettingObserver();
registerShowTouchesSettingObserver();
// 接收ACTION_USER_SWITCHED,这是关于多用户切换的操作
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
}
}, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);
updatePointerSpeedFromSettings();
updateShowTouchesFromSettings();
}
com_android_server_input_InputManagerService.cpp 中的 nativeStart(mPtr) 方法:
// com_android_server_input_InputManagerService.cpp 中:
static void nativeStart(JNIEnv* env, jclass clazz, jlong ptr) {
NativeInputManager* im = reinterpret_cast(ptr);
status_t result = im->getInputManager()->start(); // InputManager 的 start() 方法
if (result) {
jniThrowRuntimeException(env, "Input manager could not be started.");
}
}
// InputManager.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;
}
小结:nativeStart(mPtr) 方法就是把创建好的 c++ 对象 InputManager 传入,然后调用 InputManager 的start() 方法,而在 InputManager::start() 中也很简单,启动上面的两条处理线程(mReaderThread 和mDispatcherThread);
2. InputReader 与 InputReaderThread:InputReaderThread继承自C++的Thread类,Thread类封装了pthread线程工具,提供了与Java层Thread类相似的API。C++的Thread类提供了一个名为threadLoop()的纯虚函数,当线程开始运行后,将会在内建的线程循环中不断地调用threadLoop(),直到此函数返回false,则退出线程循环,从而结束线程。
InputReaderThread仅仅重写了threadLoop()函数:
// InputReader.cpp 中:
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
// InputReader.cpp 中:
void InputReader::loopOnce() {
// ... 省略
// 见 注释
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
// ...
if (count) {
processEventsLocked(mEventBuffer, count); // 我们只关注 input 事件的输入,见 2.1
}
// ...
}
注释:这里涉及到EventHub,我们就在这里开始研究一下EventHub了:
(1)EventHub的构造函数:
EventHub::EventHub(void) :
mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
mOpeningDevices(0), mClosingDevices(0),
mNeedToSendFinishedDeviceScan(false),
mNeedToReopenDevices(false), mNeedToScanDevices(true),
mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_ID);
/*(1)使用epoll_create()函数创建一个epoll对象**。EPOLL_SIZE_HINT指定最大监听个数为8
这个epoll对象将用来监听设备节点是否有数据可读(有无事件)***/
mEpollFd = epoll_create(EPOLL_SIZE_HINT);
//(2)创建一个inotify对象**。这个inotify对象将被用来监听设备节点的增删事件
mINotifyFd = inotify_init();
// 将存储设备节点的路径/dev/input作为监听对象添加到inotify对象中。当此文件夹下的设备节点
int result = inotify_add_watch(mINotifyFd, DEVICE_PATH, IN_DELETE | IN_CREATE);
/*(3)接下来将mINotifyFd作为epoll的一个监控对象。当inotify事件到来时,epoll_wait()将
立刻返回,EventHub便可从mINotifyFd中读取设备节点的增删信息,并作相应处理 */
struct epoll_event eventItem;
memset(&eventItem, 0, sizeof(eventItem));
eventItem.events = EPOLLIN; // 监听mINotifyFd可读
// 注意这里并没有使用fd字段,而使用了自定义的值EPOLL_ID_INOTIFY
eventItem.data.u32 = EPOLL_ID_INOTIFY;
// 将对mINotifyFd的监听注册到epoll对象中
result = epoll_ctl(mEpollFd, EPOLL_CTL_ADD, mINotifyFd, &eventItem);
/* 在构造函数剩余的代码中,EventHub创建了一个名为wakeFds的匿名管道,并将管道读取端
的描述符的可读事件注册到epoll对象中。因为InputReader在执行getEvents()时会因无事件而
导致其线程阻塞在epoll_wait()的调用里,然而有时希望能够立刻唤醒InputReader线程使其处
理一些请求。此时只需向wakeFds管道的写入端写入任意数据,此时读取端有数据可读,使得
epoll_wait()得以返回,从而达到唤醒InputReader线程的目的*/
// ...
}
(2)getEvents():
InputReaderThread的线程循环为Reader子系统提供了运转的动力,EventHub的工作也是由它驱动的。
InputReader::loopOnce()函数调用EventHub::getEvents()函数获取事件列表,所以这个getEvents()是EventHub运行的动力所在,几乎包含了EventHub的所有工作事项。
// 那么先看看对事件的封装:RawEvent
struct RawEvent {
nsecs_t when; /* 发生事件时的时间戳 */
int32_t deviceId; /* 产生事件的设备Id,它是由EventHub自行分配的,InputReader
以根据它从EventHub中获取此设备的详细信息 */
int32_t type; /* 事件的类型 */
int32_t code; /* 事件代码 */
int32_t value; /* 事件值 */
};
// getEvent():
size_t EventHub::getEvents(int timeoutMillis,RawEvent* buffer, size_t bufferSize) {
/* event指针指向了在buffer下一个可用于存储事件的RawEvent结构体。每存储一个事件,
event指针都回向后偏移一个元素 */
RawEvent* event = buffer;
/*capacity记录了buffer中剩余的元素数量。当capacity为0时,表示buffer已满,此时需要停
继续处理新事件,并将已处理的事件返回给调用者 */
size_t capacity = bufferSize;
/* 接下来的循环是getEvents()函数的主体。在这个循环中,会先将可用事件放入到buffer中并返回。
如果没有可用事件,则进入epoll_wait()等待事件的到来,epoll_wait()返回后会重新循环将可用
将新事件放入buffer */
for (;;){
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
/* **(1)首先进行与设备相关的工作。**某些情况下,如EventHub创建后第一次执行getEvents()函数
时,需要扫描/dev/input文件夹下的所有设备节点并将这些设备打开。另外,当设备节点的发生增
动作生时,会将设备事件存入到buffer中 */
// ...
/* **(2)处理未被InputReader取走的输入事件与设备事件。**epoll_wait()所取出的epoll_event
存储在mPendingEventItems中,mPendingEventCount指定了mPendingEventItems数组
所存储的事件个数。而mPendingEventIndex指定尚未处理的epoll_event的索引 */
while (mPendingEventIndex < mPendingEventCount) {
const struct epoll_event & eventItem = mPendingEventItems[mPendingEventIndex++];
/* 在这里分析每一个epoll_event,如果是表示设备节点可读,则读取原始事件并放置到buffer
中。如果是表示mINotifyFd可读,则设置mPendingINotify为true,当InputReader
将现有的输入事件都取出后读取mINotifyFd中的事件,并进行相应的设备加载与卸载操作。
另外,如果此epoll_event表示wakeFds的读取端有数据可读,则设置awake标志为true,
无论此次getEvents()调用有无取到事件,都不会再次进行epoll_wait()进行事件等待 */
// ...
}
//(3)如果mINotifyFd有数据可读,说明设备节点发生了增删操作
if(mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
/* 读取mINotifyFd中的事件,同时对输入设备进行相应的加载与卸载操作。这个操作必须当
InputReader将现有输入事件读取并处理完毕后才能进行,因为现有的输入事件可能来自需要
被卸载的输入设备,InputReader处理这些事件依赖于对应的设备信息 */
// ...
deviceChanged= true;
}
// 设备节点增删操作发生时,则重新执行循环体,以便将设备变化的事件放入buffer中
if(deviceChanged) {
continue;
}
// 如果此次getEvents()调用成功获取了一些事件,或者要求唤醒InputReader,则退出循环并
// 结束getEvents()的调用,使InputReader可以立刻对事件进行处理
if(event != buffer || awoken) {
break;
}
/*(4)如果此次getEvents()调用没能获取事件,说明mPendingEventItems中没有事件可用,
于是执行epoll_wait()函数等待新的事件到来,将结果存储到mPendingEventItems里,并重
置mPendingEventIndex为0 */
mPendingEventIndex = 0;
// ...
intpollResult = epoll_wait(mEpollFd, mPendingEventItems, EPOLL_MAX_EVENTS,timeoutMillis);
// ...
mPendingEventCount= size_t(pollResult);
// 从epoll_wait()中得到新的事件后,重新循环,对新事件进行处理
}
// 返回本次getEvents()调用所读取的事件数量
return event - buffer;
}
2.1 上面getEvents()返回了mEventBuffer之后,初步的处理:
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) { // 遍历获取到的event数组
int32_t type = rawEvent->type;
size_t batchSize = 1;
// 如果是常规的event事件,FIRST_SYNTHETIC_EVENT = DEVICE_ADDED (0x10000000)
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;
}
/* 把这次获取到的event数组中属于同一批次的,进一步处理,判定条件就是:常规event以
及是属于同一设备 */
processEventsForDeviceLocked(deviceId, rawEvent, batchSize); // 见 2.3
} else {
// 这里就是3种特殊的 event 类型,例如有时候打开设备的时候会有这个 ADD 事件
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId); // 见 2.2
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;
}
}
// 如果再上面没有处理完event数组中的成员,那么依次继续
count -= batchSize;
rawEvent += batchSize;
}
}
2.2 添加设备:addDeviceLocked(rawEvent->when, rawEvent->deviceId);
在EventHub中提到将事件封装成 RawEvent结构体,其中的 type 就是事件的类型,通过上面的代码可以知道一共有四种类型,接下来挑选 DEVICE_ADDED 事件看看。
void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
if (deviceIndex >= 0) {
return;
}
// 这里取之前在EventHub中解析出来的设备相关参数
InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
// 在open设备时 初始化,代表类型
// open设备调用的方法:EventHub::openDeviceLocked(const charchar *devicePath)
uint32_t classes = mEventHub->getDeviceClasses(deviceId);
int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
// 这里又创建一个 InputDervice,会根据classes选择对应的事件处理mapper与当前的设备绑定
InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
device->configure(when, &mConfig, 0);
device->reset(when);
mDevices.add(deviceId, device); // 添加这个 InputDevice
bumpGenerationLocked();
}
2.3 常规 event 的处理:
// InputReader.cpp 中 processEventsForDeviceLocked() 方法:
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
if (deviceIndex < 0) {
return;
}
// 这里根据id 取出上面添加进去的inputdevice
InputDevice* device = mDevices.valueAt(deviceIndex);
if (device->isIgnored()) {
return;
}
device->process(rawEvents, count); // 这里调用了一个process的函数
}
// InputReader.cpp 中 process() 方法:
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
// 这里有个map个数,在create时 会根据classes类型去匹配处理map,一般都是匹配一个
size_t numMappers = mMappers.size();
// 遍历事件数组,依次去处理
for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
if (mDropUntilNextSync) {
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
mDropUntilNextSync = false;
} else {
ALOGD("Dropped input event while waiting for next input sync.");
}
} 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 函数,开始分发流程,见 3.1
mapper->process(rawEvent);
}
}
}
}
3. input事件分发:mapper->process(rawEvent)
在 2.2 中提到 createDeviceLocked() 这个方法给device添加绑定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);
}
// ...
// 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));
}
return device;
}
3.1 分发前的处理:
我们就以SingleTouchInputMapper为例
void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
TouchInputMapper::process(rawEvent); // 调用父类的process
mSingleTouchMotionAccumulator.process(rawEvent);
}
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);
}
}
/**
以下语句均是将输入事件信息转存至类成员变量中:
mCursorButtonAccumulator.process(rawEvent);
mCursorScrollAccumulator.process(rawEvent);
mTouchButtonAccumulator.process(rawEvent);
mSingleTouchMotionAccumulator.process(rawEvent);
**/
输入事件分发的关键在 TouchInputMapper::sync() 方法中:这个同步函数比较长,下面是简化后的代码,我们之关注一下事件的分发就行了;
void TouchInputMapper::sync(nsecs_t when) {
// Sync button state.
mCurrentButtonState = mTouchButtonAccumulator.getButtonState()
| mCursorButtonAccumulator.getButtonState();
// Sync scroll state.
mCurrentRawVScroll = mCursorScrollAccumulator.getRelativeVWheel();
mCurrentRawHScroll = mCursorScrollAccumulator.getRelativeHWheel();
mCursorScrollAccumulator.finishSync();
// Sync touch state.
bool havePointerIds = true;
mCurrentRawPointerData.clear();
/*调用子类的syncTouch,这里是 SingleTouchMotionAccumulator的syncTouch(),
更新ABS 坐标值,我这里是把数据存入到mCurrentRawPointerData中供下面cook */
syncTouch(when, &havePointerIds);
// Reset state that we will compute below.
mCurrentFingerIdBits.clear();
mCurrentStylusIdBits.clear();
mCurrentMouseIdBits.clear();
mCurrentCookedPointerData.clear(); // 先清除一下
if (mDeviceMode == DEVICE_MODE_DISABLED) {
// Drop all input if the device is disabled.
mCurrentRawPointerData.clear();
mCurrentButtonState = 0;
} else {
if (mDeviceMode == DEVICE_MODE_POINTER) {
PointerUsage pointerUsage = mPointerUsage;
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(mCurrentButtonState);
mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,
mCurrentCookedPointerData.idToIndex,
mCurrentCookedPointerData.touchingIdBits);
}
// 分发事件,这里的三个方法最终都回调用 dispatchMotion()
//
dispatchHoverExit(when, policyFlags);
dispatchTouches(when, policyFlags);
dispatchHoverEnterAndMove(when, policyFlags);
}
// 之后的代码是一些数据保存之类的操作
// ...
}
// ...
mCurrentRawVScroll = 0;
mCurrentRawHScroll = 0;
}
dispatchMotion():
void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
int32_t action, 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 args(when, getDeviceId(), source, policyFlags,
action, flags, metaState, buttonState, edgeFlags,
mViewport.displayId, pointerCount, pointerProperties, pointerCoords,
xPrecision, yPrecision, downTime);
// 这里的 getListener() 就是我们之前提到的 传入mDispatcher作为回调,只是做了进一步封装;
getListener()->notifyMotion(&args);
}
3.2 InputDispatcher 和 InputDispatcherThread:分发输入事件
InputDispatcherThread 和之前的 InputReaderThread 一样,先看看 threadLoop()方法;
// threadLoop() 方法:
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}
// dispatchOnce() 方法:
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{
AutoMutex _l(mLock);
mDispatcherIsAliveCondition.broadcast();
// 第一次进来时mCommandQueue是空,能进入此分支;
· // 然后在 dispatchOnceInnerLocked() 方法中 return;
// 最终在 mLooper->pollOnce(timeoutMillis) 休眠等待;
if (!haveCommandsLocked()) { // 为空则开始处理事件
dispatchOnceInnerLocked(&nextWakeupTime);
}
// Run all pending commands if there are any.
// If any commands were run then force the next poll to wake up immediately.
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
} // release lock
// Wait for callback or timeout or wake. (make sure we round up, not down)
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
// looper进入休眠等待,wake() 方法唤醒(向fd中写入数据就会唤醒);
mLooper->pollOnce(timeoutMillis);
}
上面的 dispatcherOnce() 方法在第一次进入时,会进入休眠状态,那么输入事件的时候是如何调用的呢?这就是我们 3.1 中的 getListener()->notifyMotion(&args),也就是Dispatcher的 notifyMotion() 方法:
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
if (!validateMotionEvent(args->action, args->pointerCount, args->pointerProperties)) {
return; // 校验MotionEvent的参数
}
// ...
bool needWake;
{ // acquire lock
mLock.lock();
if (shouldSendMotionToInputFilterLocked(args)) {
mLock.unlock();
MotionEvent event;
event.initialize(args->deviceId, args->source, args->action, args->flags,
args->edgeFlags, args->metaState, args->buttonState, 0, 0,
args->xPrecision, args->yPrecision,
args->downTime, args->eventTime,
args->pointerCount, args->pointerProperties, args->pointerCoords);
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
return; // event was consumed by the filter
}
mLock.lock();
}
// Just enqueue a new motion event.
// 解析成一个新的MotionEntry:newEntry
MotionEntry* newEntry = new MotionEntry(args->eventTime,
args->deviceId, args->source, policyFlags,
args->action, args->flags, args->metaState, args->buttonState,
args->edgeFlags, args->xPrecision, args->yPrecision, args->downTime,
args->displayId,
args->pointerCount, args->pointerProperties, args->pointerCoords, 0, 0);
needWake = enqueueInboundEventLocked(newEntry); //加入队列
mLock.unlock();
} // release lock
if (needWake) {
mLooper->wake(); // 如果需要唤醒InputDispatcher线程, 则调用Looper的唤醒方法
}
}
加入输入事件队列:enqueueInboundEventLocked(EventEntry* entry) 方法
bool InputDispatcher::enqueueInboundEventLocked(EventEntry* entry) {
bool needWake = mInboundQueue.isEmpty(); // 如果队列为空 , 则需要唤醒
mInboundQueue.enqueueAtTail(entry); // 插入到mInboundQueue队列尾部
// ...
return needWake;
}
InputDispatcherThread::threadLoop() 会一直执行mDispatcher->dispatchOnce() 方法,唤醒 looper后,在dispatchOnce() 方法中继续调用 dispatchOnceInnerLocked(&nextWakeupTime)来处理输入事件,下面是这个方法的代码:
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
nsecs_t currentTime = now();
// 判断事件分发是否允许,也就是在未开机、IMS未成功启动、关机等状态下是不可用的,默认值是false
if (!mDispatchEnabled) {
resetKeyRepeatLocked(); //重置重复按键次数
}
//判断分发线程是否被冻结,是否可以配发,默认值是false
if (mDispatchFrozen) {
return;
}
//判断此处是不是正在切换应用,以便在home和endcall按键到来时,及时丢弃之前的事件,而直接响应特殊键
bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
if (mAppSwitchDueTime < *nextWakeupTime) {
*nextWakeupTime = mAppSwitchDueTime;
}
// Ready to start a new event.
//mPendingEvent是即将要被配发的事件,派发完成置为null,此处是判断是否正在配发事件
if (! mPendingEvent) {
if (mInboundQueue.isEmpty()) { // 如果Event队列为空的话
if (isAppSwitchDue) {
// The inbound queue is empty so the app switch key we were waiting
// for will never arrive. Stop waiting for it.
resetPendingAppSwitchLocked(false);
isAppSwitchDue = false;
}
// Synthesize a key repeat if appropriate.
if (mKeyRepeatState.lastKeyEntry) {
if (currentTime >= mKeyRepeatState.nextRepeatTime) {
mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
} else {
if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
*nextWakeupTime = mKeyRepeatState.nextRepeatTime;
}
}
}
// Nothing to do if there is no pending event.
if (!mPendingEvent) { // 如果没有要处理的事件 , 则返回
return;
}
} else {
// Inbound queue has at least one entry.
mPendingEvent = mInboundQueue.dequeueAtHead(); // 有Event时,取出第一个Event;
traceInboundQueueLengthLocked();
}
// Poke user activity for this event.
if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
pokeUserActivityLocked(mPendingEvent);
}
// 重置此次事件分发的ANR超时时间,如果超过5秒,就会产生ANR
resetANRTimeoutsLocked();
}
// Now we have an event to dispatch.
// All events are eventually dequeued and processed this way, even if we intend to drop them.
ALOG_ASSERT(mPendingEvent != NULL);
bool done = false;
DropReason dropReason = DROP_REASON_NOT_DROPPED;
if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
dropReason = DROP_REASON_POLICY;
} else if (!mDispatchEnabled) {
dropReason = DROP_REASON_DISABLED;
}
if (mNextUnblockedEvent == mPendingEvent) {
mNextUnblockedEvent = NULL;
}
switch (mPendingEvent->type) {
// 处理Configuration Change消息 , 即屏幕旋转等等
case EventEntry::TYPE_CONFIGURATION_CHANGED: {
ConfigurationChangedEntry* typedEntry =
static_cast(mPendingEvent);
done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
break;
}
// 处理设备重置消息
case EventEntry::TYPE_DEVICE_RESET: {
DeviceResetEntry* typedEntry =
static_cast(mPendingEvent);
done = dispatchDeviceResetLocked(currentTime, typedEntry);
dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
break;
}
// 处理Key按键消息
case EventEntry::TYPE_KEY: {
KeyEntry* typedEntry = static_cast(mPendingEvent);
if (isAppSwitchDue) {
if (isAppSwitchKeyEventLocked(typedEntry)) {
resetPendingAppSwitchLocked(true);
isAppSwitchDue = false;
} else if (dropReason == DROP_REASON_NOT_DROPPED) {
dropReason = DROP_REASON_APP_SWITCH;
}
}
if (dropReason == DROP_REASON_NOT_DROPPED
&& isStaleEventLocked(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
// 判断时触屏事件时:
case EventEntry::TYPE_MOTION: {
MotionEntry* typedEntry = static_cast(mPendingEvent);
if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
dropReason = DROP_REASON_APP_SWITCH;
}
if (dropReason == DROP_REASON_NOT_DROPPED
&& isStaleEventLocked(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
done = dispatchMotionLocked(currentTime, typedEntry,
&dropReason, nextWakeupTime); // 分发事件
break;
}
default:
ALOG_ASSERT(false);
break;
}
if (done) {
if (dropReason != DROP_REASON_NOT_DROPPED) {
dropInboundEventLocked(mPendingEvent, dropReason); // 从配发队列里面丢弃事件
}
releasePendingEventLocked();
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
分发事件:
bool InputDispatcher::dispatchMotionLocked(
nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
// 找到目标窗口
Vector inputTargets;
bool conflictingPointerActions = false;
int32_t injectionResult;
if (isPointerEvent) {
// 如果是手指事件的话 ,则找到Touch窗口:关键代码1
injectionResult = findTouchedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
} else {
// 如果不是手指触摸事件 , 比如轨迹球事件的话 , 则找到Focus窗口
injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);
}
// 如果找到窗口失败, 返回
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
// 开始向窗口分发事件:关键代码2
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
(关键代码1)找到Touch窗口findFocusedWindowTargetsLocked():也是这个方法限制了不同app在不同窗口层级时,上面的app不能把触屏事件分发给下面的app;
int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
const MotionEntry* entry, Vector& inputTargets, nsecs_t* nextWakeupTime,
bool* outConflictingPointerActions) {
// ...
if (newGesture || (isSplit && maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN)) {
//从MotionEntry中获取坐标点
int32_t pointerIndex = getMotionEventActionPointerIndex(action);
int32_t x = int32_t(entry->pointerCoords[pointerIndex].
getAxisValue(AMOTION_EVENT_AXIS_X));
int32_t y = int32_t(entry->pointerCoords[pointerIndex].
getAxisValue(AMOTION_EVENT_AXIS_Y));
sp newTouchedWindowHandle;
bool isTouchModal = false;
size_t numWindows = mWindowHandles.size();//1
// 遍历窗口,找到触摸过的窗口和窗口之外的外部目标
for (size_t i = 0; i < numWindows; i++) {//2
//获取InputDispatcher中代表窗口的windowHandle
sp windowHandle = mWindowHandles.itemAt(i);
//得到窗口信息windowInfo
const InputWindowInfo* windowInfo = windowHandle->getInfo();
if (windowInfo->displayId != displayId) {
//如果displayId不匹配,开始下一次循环
continue;
}
//获取窗口的flag
int32_t flags = windowInfo->layoutParamsFlags;
//如果窗口时可见的
if (windowInfo->visible) {
//如果窗口的flag不为FLAG_NOT_TOUCHABLE(窗口是touchable)
if (! (flags & InputWindowInfo::FLAG_NOT_TOUCHABLE)) {
// 如果窗口是focusable或者flag不为FLAG_NOT_FOCUSABLE,则说明该窗口是"可触摸模式"
isTouchModal = (flags & (InputWindowInfo::FLAG_NOT_FOCUSABLE
| InputWindowInfo::FLAG_NOT_TOUCH_MODAL)) == 0;//3
//如果窗口是 可触摸模式或者坐标点落在窗口之上(找到目标窗口)
if (isTouchModal || windowInfo->touchableRegionContainsPoint(x, y)) {
newTouchedWindowHandle = windowHandle;//4
break; // found touched window, exit window loop
}
}
if (maskedAction == AMOTION_EVENT_ACTION_DOWN
&& (flags & InputWindowInfo::FLAG_WATCH_OUTSIDE_TOUCH)) {
//将符合条件的窗口放入TempTouchState中,以便后续处理。
mTempTouchState.addOrUpdateWindow(
windowHandle, InputTarget::FLAG_DISPATCH_AS_OUTSIDE, BitSet32(0));//5
}
}
// ...
}
} else{
// ...
}
// ...
// 把临时存放窗口的 TempTouchState 加入到全局的 inputTargets 中
for (size_t i = 0; i < mTempTouchState.windows.size(); i++) {
const TouchedWindow& touchedWindow = mTempTouchState.windows.itemAt(i);
addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
touchedWindow.pointerIds, inputTargets);
}
// ...
}
(关键代码2)开始向窗口分发事件 dispatchEventLocked(currentTime, entry, inputTargets):
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
EventEntry* eventEntry, const Vector& inputTargets) {
ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
pokeUserActivityLocked(eventEntry);
for (size_t i = 0; i < inputTargets.size(); i++) { // 遍历 inputTargets
const InputTarget& inputTarget = inputTargets.itemAt(i);
ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
if (connectionIndex >= 0) {
// 获取跨进程通讯的连接;
sp connection = mConnectionsByFd.valueAt(connectionIndex);
// 通过拿到的连接进行分发;
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
} else {
// ...
}
}
}
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget) ->
enqueueDispatchEntriesLocked(currentTime, connection, splitMotionEntry, inputTarget) ->
startDispatchCycleLocked(currentTime, connection)
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp& connection) {
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ startDispatchCycle",
connection->getInputChannelName());
#endif
while (connection->status == Connection::STATUS_NORMAL&& !connection->outboundQueue.isEmpty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.head;
dispatchEntry->deliveryTime = currentTime;
// Publish the event.
status_t status;
EventEntry* eventEntry = dispatchEntry->eventEntry;
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
// ... key 事件
break;
}
case EventEntry::TYPE_MOTION: {
MotionEntry* motionEntry = static_cast(eventEntry);
PointerCoords scaledCoords[MAX_POINTERS];
const PointerCoords* usingCoords = motionEntry->pointerCoords;
// Set the X and Y offset depending on the input source.
float xOffset, yOffset, scaleFactor;
if ((motionEntry->source & AINPUT_SOURCE_CLASS_POINTER)
&& !(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
scaleFactor = dispatchEntry->scaleFactor;
xOffset = dispatchEntry->xOffset * scaleFactor;
yOffset = dispatchEntry->yOffset * scaleFactor;
if (scaleFactor != 1.0f) {
for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
scaledCoords[i] = motionEntry->pointerCoords[i];
scaledCoords[i].scale(scaleFactor);
}
usingCoords = scaledCoords;
}
} else {
xOffset = 0.0f;
yOffset = 0.0f;
scaleFactor = 1.0f;
// We don't want the dispatch target to know.
if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
for (uint32_t i = 0; i < motionEntry->pointerCount; i++) {
scaledCoords[i].clear();
}
usingCoords = scaledCoords;
}
}
// Publish the motion event.
// 通过连接分发给远程端;
status = connection->inputPublisher.publishMotionEvent(dispatchEntry->seq,
motionEntry->deviceId, motionEntry->source,
dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
motionEntry->edgeFlags, motionEntry->metaState, motionEntry->buttonState,
xOffset, yOffset,
motionEntry->xPrecision, motionEntry->yPrecision,
motionEntry->downTime, motionEntry->eventTime,
motionEntry->pointerCount, motionEntry->pointerProperties,
usingCoords);
break;
}
// Check the result.
if (status) {
// ...
return;
}
// Re-enqueue the event on the wait queue.
connection->outboundQueue.dequeue(dispatchEntry);
traceOutboundQueueLengthLocked(connection);
connection->waitQueue.enqueueAtTail(dispatchEntry);
traceWaitQueueLengthLocked(connection);
}
}