关键字的理解
下面是在分析的过程中遇到的一些关键字,应该可以更好的帮助读者理解。
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS /
#define EV_SYN 0x00 同步事件
#define EV_KEY 0x01 按键事件
#define EV_REL 0x02 相对坐标
#define EV_ABS 0x03 绝对坐标
/ WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS /
#define EV_MSC 0x04 其它
#define EV_SW 0x05
#define EV_LED 0x11 LED
#define EV_SND 0x12 声音
/ WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define EV_REP 0x14 Repeat
#define EV_FF 0x15 力反馈
#define EV_PWR 0x16 电源
#define EV_FF_STATUS 0x17 状态
InputReader事件处理时序图
InputReader事件处理分析
从事件系统初始化一章可以知道,InputReaderThread启动之后会调用threadLoop,当返回true会一直循环。
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
Vector<InputDeviceInfo> inputDevices;
{ // acquire lock
AutoMutex _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
AutoMutex _l(mLock);//当有需要处理的事件时一定要枷锁,将本次上报事件处理完毕后再继续获取事件。
mReaderIsAliveCondition.broadcast();
if (count) {
//开始处理事件
processEventsLocked(mEventBuffer, count);
}
if (mNextTimeout != LLONG_MAX) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
if (now >= mNextTimeout) {
#if DEBUG_RAW_EVENTS
ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
#endif
mNextTimeout = LLONG_MAX;
timeoutExpiredLocked(now);
}
}
//设备是否变化,若是变化则获取输入设备
if (oldGeneration != mGeneration) {
inputDevicesChanged = true;
getInputDevicesLocked(inputDevices);
}
} // release lock
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
//通知上层设备已经发生变化,mPolicy的实现是在com_android_server_input_InputManagerService.cpp中
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.
//通知InputDispatcher,事件到来了,赶紧吃吧
mQueuedListener->flush();
}
接下来主要分析对通过EvengHub读取的事件进一步处理了。
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) {
int32_t type = rawEvent->type;
size_t batchSize = 1;
//此处判断是为了甄别设备是否增删或增删完成操作类型,不是才会执行此逻辑;否则执行else
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: %d Count: %d", batchSize, count);
#endif
//处理设备事件
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {
//处理设备的增删扫描事件或增删事件的完成
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
//此处主要是把EventHub中的Device转化为InputReader的InputDevice
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
handleConfigurationChangedLocked(rawEvent->when);
break;
default:
ALOG_ASSERT(false); // can't happen
break;
}
}
count -= batchSize;
rawEvent += batchSize;
}
}
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
//此处用于判断输入设备是否已经加载
if (deviceIndex < 0) {
ALOGW("Discarding event for unknown deviceId %d.", deviceId);
return;
}
InputDevice* device = mDevices.valueAt(deviceIndex);
//此设备是否有对应的Mapper(Mapper相当与事件的加工厂,如果没有处理的工厂就不需要继续进行下去了)
if (device->isIgnored()) {
//ALOGD("Discarding event for ignored deviceId %d.", deviceId);
return;
}
//屏蔽掉无用的事件就可以处理了
device->process(rawEvents, count);
}
//其实下面的很简单,就是把RawEvent交给每个InputMapper进行加工,然后将加工好的事件交给InputDispatcher
//进行分发处理。
void InputDevice::process(const RawEvent* rawEvents, size_t count) {
// Process all of the events in order for each mapper.
// We cannot simply ask each mapper to process them in bulk because mappers may
// have side-effects that must be interleaved. For example, joystick movement events and
// gamepad button presses are handled by different mappers but they should be dispatched
// in the order received.
size_t numMappers = mMappers.size();
......
} else {
for (size_t i = 0; i < numMappers; i++) {
InputMapper* mapper = mMappers[i];
mapper->process(rawEvent);
}
}
}
}
每个InputMapper加工厂对事件的加工在这里就不介绍了,有兴趣的可以自行研究。
至于InputReader怎么把加工的事件通知到InputDispatcher的,上面的时序图大家可以基本上了解到。其实通知的关键代码如下:
getListener()->notify***(&args);
好了,InputReader就写道这了。