事件的开始是从eventhub开始的,我们先来看下流程图
事件派发的整个流程比较复杂,我们只看几个比较重要点的地方,从loopOnce开始
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
Vector 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->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();
}
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count)
{
for (const RawEvent* rawEvent = rawEvents; count;)
{
int32_t type = rawEvent->type;
size_t batchSize = 1;
ALOGD("rawEvent->type: %d ", rawEvent->type);//event类型 参考http://wenku.baidu.com/link?url=HLS1P7Hn8qqscyPbZY2JhpuqZLE2n5uXPnBi4xHUbKvNRqUVdGYaRYK5k0BciIWyWZigNels-losqAfS8nRTDnuaNpwuwSTfF0DAXdmYt2e
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {//小于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
convertEvent(rawEvent,batchSize); //对事件做一些处理并存到mConvertEventBuffer
if(batchSize > 0) {//有事件需要出处理
int32_t convertdeviceId = mConvertEventBuffer[0].deviceId;
processEventsForDeviceLocked(convertdeviceId, mConvertEventBuffer, 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;
}
}
#define EV_SYN 0x00
#define EV_KEY 0x01 //按键
#define EV_REL 0x02 //相对坐标(轨迹球)
#define EV_ABS 0x03 //绝对坐标
#define EV_MSC 0x04 //其他
#define EV_SW 0x05
#define EV_LED 0x11 //LED
#define EV_SND 0x12//声音
#define EV_REP 0x14//repeat
#define EV_FF 0x15
#define EV_PWR 0x16
#define EV_FF_STATUS 0x17
#define EV_MAX 0x1f
#define EV_CNT (EV_MAX+1)
convertEvent对事件做一些处理并存到mConvertEventBuffer,接着调用processEventsForDeviceLocked
void InputReader::processEventsForDeviceLocked(int32_t deviceId,
const RawEvent* rawEvents, size_t count) {
ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
if (deviceIndex < 0) {
ALOGW("Discarding event for unknown deviceId %d.", deviceId);
return;
}
InputDevice* device = mDevices.valueAt(deviceIndex);
if (device->isIgnored()) {
//ALOGD("Discarding event for ignored deviceId %d.", deviceId);
return;
}
device->process(rawEvents, count);//调用InputDevice::process
}
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
ALOGW("KeyboardInputMapper::process.rawEvent->type = %d", rawEvent->type);
switch (rawEvent->type) {
case EV_KEY: {
bool find = false;
bool down = false;
// bool currentindex = 0;
int currentindex = 0;
if(mIsRepeatMode)//重复按键模式
{
ALOGW("mIsRepeatMode = true");
if(rawEvent->value != 0)
{
for(int i = 0;i < MAX_KEYDOWNNUM;i++)
{
if(mCurrentDown[i] == true)
{
down = true;
}
}
if(down == false)
{
ALOGW("down = false");
for(int i = 0;i < MAX_KEYDOWNNUM;i++)
{
if(mCurrentDown[i] == false)
{
currentindex = i;
break ;
}
}
mCurrentDown[currentindex] = true;
mCurrentScanCode[currentindex] = rawEvent->code;
goto processCurrentEvent;
}
else
{
for(int i = 0;i < MAX_KEYDOWNNUM;i++)
{
if(mCurrentScanCode[i] == rawEvent->code)
{
find = true;
}
}
if(find == false)
{
for(int i = 0;i < MAX_KEYDOWNNUM;i++)
{
if(mCurrentDown[i] == false)
{
currentindex = i;
break;
}
}
mCurrentDown[currentindex] = true;
mCurrentScanCode[currentindex] = rawEvent->code;
goto processCurrentEvent;
}
}
}
else
{
for(int i = 0;i < MAX_KEYDOWNNUM;i++)
{
if(mCurrentScanCode[i] == rawEvent->code)
{
currentindex = i;
find = true;
break;
}
}
if(find == true)
{
mCurrentDown[currentindex] = false;
mCurrentScanCode[currentindex] = 0;
goto processCurrentEvent;
}
}
}
else
{
goto processCurrentEvent;
}
return ;
processCurrentEvent:
int32_t scanCode = rawEvent->code;
int32_t usageCode = mCurrentHidUsage;
mCurrentHidUsage = 0;
if (isKeyboardOrGamepadKey(scanCode)) {//键盘或者手柄
int32_t keyCode;
uint32_t flags;
ALOGW("mapKey");
if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {//根据.kl文件映射键值
keyCode = AKEYCODE_UNKNOWN;
flags = 0;
}
processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);//处理键值
}
break;
}
case EV_MSC: {
if (rawEvent->code == MSC_SCAN) {
mCurrentHidUsage = rawEvent->value;//设置mCurrentHidUsage
}
break;
}
case EV_SYN: {
if (rawEvent->code == SYN_REPORT) {//事件的结束
mCurrentHidUsage = 0;//设置mCurrentHidUsage
}
}
}
ALOGW("Exit KeyboardInputMapper::process");
}
调用mapKey根据配置文件映射键值,最后调用processKey,processKey又会调用notifyKey,最终会调用到InputDispatcher的notifyKey
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
ALOGD("notifyKey - eventTime=%lld, deviceId=%d, source=0x%x, policyFlags=0x%x, action=0x%x, "
"flags=0x%x, keyCode=0x%x, scanCode=0x%x, metaState=0x%x, downTime=%lld",
args->eventTime, args->deviceId, args->source, args->policyFlags,
args->action, args->flags, args->keyCode, args->scanCode,
args->metaState, args->downTime);
#endif
if (!validateKeyEvent(args->action)) {//验证action参数是否正确
return;
}
uint32_t policyFlags = args->policyFlags;
int32_t flags = args->flags;
int32_t metaState = args->metaState;
if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
policyFlags |= POLICY_FLAG_VIRTUAL;
flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
}
if (policyFlags & POLICY_FLAG_ALT) {//检查一下同时是否有ALT和SHIFT键被按下
metaState |= AMETA_ALT_ON | AMETA_ALT_LEFT_ON;
}
if (policyFlags & POLICY_FLAG_ALT_GR) {
metaState |= AMETA_ALT_ON | AMETA_ALT_RIGHT_ON;
}
if (policyFlags & POLICY_FLAG_SHIFT) {
metaState |= AMETA_SHIFT_ON | AMETA_SHIFT_LEFT_ON;
}
if (policyFlags & POLICY_FLAG_CAPS_LOCK) {
metaState |= AMETA_CAPS_LOCK_ON;
}
if (policyFlags & POLICY_FLAG_FUNCTION) {
metaState |= AMETA_FUNCTION_ON;
}
policyFlags |= POLICY_FLAG_TRUSTED;
KeyEvent event;
event.initialize(args->deviceId, args->source, args->action,
flags, args->keyCode, args->scanCode, metaState, 0,
args->downTime, args->eventTime);
ALOGD("lijj before mPolicy->interceptKeyBeforeQueueing");
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags); //调度前处理 会调用到interceptKeyBeforeDispatching 的interceptKeyBeforeDispatching
ALOGD("lijj after mPolicy->interceptKeyBeforeQueueing");
if (policyFlags & POLICY_FLAG_WOKE_HERE) {
flags |= AKEY_EVENT_FLAG_WOKE_HERE;
}
bool needWake;
{ // acquire lock
mLock.lock();
if (shouldSendKeyToInputFilterLocked(args)) {
mLock.unlock();
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy->filterInputEvent(&event, policyFlags)) {
return; // event was consumed by the filter
}
mLock.lock();
}
int32_t repeatCount = 0;
KeyEntry* newEntry = new KeyEntry(args->eventTime,//封装成一个KeyEntry结构
args->deviceId, args->source, policyFlags,
args->action, flags, args->keyCode, args->scanCode,
metaState, repeatCount, args->downTime);
needWake = enqueueInboundEventLocked(newEntry);//interceptKeyBeforeQueueing
mLock.unlock();
} // release lock
if (needWake) {
mLooper->wake();//唤醒InputDispatccherThread线程
}
}
在正式分发按键前,会调用interceptKeyBeforeQueueing对按键做一些预先处理,该函数最终会调用到PhoneWindowManager的interceptKeyBeforeQueueing,在里面会对一些系统的按键如
音量键、电源键、耳机进行一些处理,接着把按键消息封装程一个KeyEntry,并调用enqueueInboundEventLocked插入mInboundQueue队列,最后唤醒InputDispatccherThread线程,这个过程中可能会唤醒或者睡眠系统
回到notifyKey唤醒InputDispatcherThread,运行dispatchOnce
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
mDispatcherIsAliveCondition.broadcast();
// Run a dispatch loop if there are no pending commands.
// The dispatch loop might enqueue commands to run afterwards.
if (!haveCommandsLocked()) {//mCommandQueue不为空
dispatchOnceInnerLocked(&nextWakeupTime);//调用dispatchOnceInnerLocked函数来进一步处理
}
ALOGD("InputDispatcher::dispatchOnce");
// Run all pending commands if there are any.
// If any commands were run then force the next poll to wake up immediately.
if (runCommandsLockedInterruptible()) {//运行command
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);
mLooper->pollOnce(timeoutMillis);
}
我们看handleEvent
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
ALOGD("NativeInputEventReceiver::handleEvent");
if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
ALOGE("channel '%s' ~ Publisher closed input channel or an error occurred. "
"events=0x%x", getInputChannelName(), events);
return 0; // remove the callback
}
if (!(events & ALOOPER_EVENT_INPUT)) {
ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
"events=0x%x", getInputChannelName(), events);
return 1;
}
JNIEnv* env = AndroidRuntime::getJNIEnv();
status_t status = consumeEvents(env, false /*consumeBatches*/, -1);
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
return status == OK || status == NO_MEMORY ? 1 : 0;
}
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime) {
#if DEBUG_DISPATCH_CYCLE
// ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%lld.",
// getInputChannelName(), consumeBatches ? "true" : "false", frameTime);
#endif
ALOGD("NativeInputEventReceiver::consumeEvents");
if (consumeBatches) {
mBatchedInputEventPending = false;
}
bool skipCallbacks = false;
for (;;) {
uint32_t seq;
InputEvent* inputEvent;
status_t status = mInputConsumer.consume(&mInputEventFactory,
consumeBatches, frameTime, &seq, &inputEvent);//取出按键
if (status) {
if (status == WOULD_BLOCK) {
if (!skipCallbacks && !mBatchedInputEventPending
&& mInputConsumer.hasPendingBatch()) {//暂停
// There is a pending batch. Come back later.
mBatchedInputEventPending = true;
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ Dispatching batched input event pending notification.",
getInputChannelName());
#endif
env->CallVoidMethod(mReceiverObjGlobal,
gInputEventReceiverClassInfo.dispatchBatchedInputEventPending);
if (env->ExceptionCheck()) {
ALOGE("Exception dispatching batched input events.");
mBatchedInputEventPending = false; // try again later
}
}
return OK;
}
ALOGE("channel '%s' ~ Failed to consume input event. status=%d",
getInputChannelName(), status);
return status;
}
assert(inputEvent);
if (!skipCallbacks) {
jobject inputEventObj;
switch (inputEvent->getType()) {
case AINPUT_EVENT_TYPE_KEY:
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ Received key event.", getInputChannelName());
#endif
inputEventObj = android_view_KeyEvent_fromNative(env, //转换
static_cast(inputEvent));
break;
case AINPUT_EVENT_TYPE_MOTION:
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ Received motion event.", getInputChannelName());
#endif
inputEventObj = android_view_MotionEvent_obtainAsCopy(env,
static_cast(inputEvent));
break;
default:
assert(false); // InputConsumer should prevent this from ever happening
inputEventObj = NULL;
}
if (inputEventObj) {
#if DEBUG_DISPATCH_CYCLE
ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName());
#endif
env->CallVoidMethod(mReceiverObjGlobal, //调用java层处理
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
if (env->ExceptionCheck()) {
ALOGE("Exception dispatching input event.");
skipCallbacks = true;
}
} else {
ALOGW("channel '%s' ~ Failed to obtain event object.", getInputChannelName());
skipCallbacks = true;
}
}
if (skipCallbacks) {
mInputConsumer.sendFinishedSignal(seq, false);
}
}
}
到这里,事件消息就已经处理完成了,主要是是那个点:
1、interceptKeyBeforeQueueing
2、doInterceptKeyBeforeDispatchingLockedInterruptible
3、dispatchInputEvent
这里面的具体过程比较复杂,涉及的模块也比较多,流程图都有列出来了。