该篇文章仅分析notifyKey之后的流程,InputReader怎么读取之类的本文不关心.本文重点关注InputDispatcher和java层的交互,包括调用interceptKeyBeforeQueueing和interceptKeyBeforeDispatching方法,以及有辅助服务拦截按键时的处理.
1.notifyKey主函数
void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
...
...
...
KeyEvent event;
event.initialize(args->deviceId, args->source, args->action,
flags, keyCode, args->scanCode, metaState, 0,
args->downTime, args->eventTime);
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
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,
args->deviceId, args->source, policyFlags,
args->action, flags, keyCode, args->scanCode,
metaState, repeatCount, args->downTime);
needWake = enqueueInboundEventLocked(newEntry);
mLock.unlock();
} // release lock
if (needWake) {
mLooper->wake();
}
}
主函数中有四个重要的调用,我们需要分别分析:
1.mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);//最终会调用到PWM中对应的方法
2.shouldSendKeyToInputFilterLocked(args)//和辅助服务相关
3.needWake = enqueueInboundEventLocked(newEntry);//把按键加入队列
4.mLooper->wake();//唤醒线程,从队列中去除按键事件执行分发
首先分析第一步interceptKeyBeforeQueueing,mPolicy其实是NativeInputManager对象,去该对象中看看具体调用:
void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
uint32_t& policyFlags) {
// Policy:
// - Ignore untrusted events and pass them along.
// - Ask the window manager what to do with normal events and trusted injected events.
// - For normal events wake and brighten the screen if currently off or dim.
bool interactive = mInteractive.load();
if (interactive) {
policyFlags |= POLICY_FLAG_INTERACTIVE;
}
if ((policyFlags & POLICY_FLAG_TRUSTED)) {
nsecs_t when = keyEvent->getEventTime();
JNIEnv* env = jniEnv();
jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
jint wmActions;
if (keyEventObj) {
wmActions = env->CallIntMethod(mServiceObj,
gServiceClassInfo.interceptKeyBeforeQueueing,
keyEventObj, policyFlags);
if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
wmActions = 0;
}
android_view_KeyEvent_recycle(env, keyEventObj);
env->DeleteLocalRef(keyEventObj);
} else {
ALOGE("Failed to obtain key event object for interceptKeyBeforeQueueing.");
wmActions = 0;
}
handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
} else {
if (interactive) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
}
}
}
其中会主要是调用env->CallIntMethod(mServiceObj,gServiceClassInfo.interceptKeyBeforeQueueing,keyEventObj, policyFlags).该方法会调用InputManagerService的interceptKeyBeforeQueueing,InputManagerService又会调用PhoneWindowManager的interceptKeyBeforeQueueing,然后会有一个返回值赋给wmActions,而接下来handleInterceptActions会根据wmActions的值来更新policyFlags:
void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
uint32_t& policyFlags) {
if (wmActions & WM_ACTION_PASS_TO_USER) {
policyFlags |= POLICY_FLAG_PASS_TO_USER;
} else {
#if DEBUG_INPUT_DISPATCHER_POLICY
ALOGD("handleInterceptActions: Not passing key to user.");
#endif
}
}
也就意味着我们在PhoneWindowManager中可以通过返回值来控制policyFlags的值,事件分发过程中多次判断该值,决定要不要继续分发.